UNPKG

10.2 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3var tslib_1 = require("tslib");
4/**
5 * Loads database entities for all operate subjects which do not have database entity set.
6 * All entities that we load database entities for are marked as updated or inserted.
7 * To understand which of them really needs to be inserted or updated we need to load
8 * their original representations from the database.
9 */
10var SubjectDatabaseEntityLoader = /** @class */ (function () {
11 // ---------------------------------------------------------------------
12 // Constructor
13 // ---------------------------------------------------------------------
14 function SubjectDatabaseEntityLoader(queryRunner, subjects) {
15 this.queryRunner = queryRunner;
16 this.subjects = subjects;
17 }
18 // ---------------------------------------------------------------------
19 // Public Methods
20 // ---------------------------------------------------------------------
21 /**
22 * Loads database entities for all subjects.
23 *
24 * loadAllRelations flag is used to load all relation ids of the object, no matter if they present in subject entity or not.
25 * This option is used for deletion.
26 */
27 SubjectDatabaseEntityLoader.prototype.load = function (operationType) {
28 return tslib_1.__awaiter(this, void 0, void 0, function () {
29 var promises;
30 var _this = this;
31 return tslib_1.__generator(this, function (_a) {
32 switch (_a.label) {
33 case 0:
34 promises = this.groupByEntityTargets().map(function (subjectGroup) { return tslib_1.__awaiter(_this, void 0, void 0, function () {
35 var e_1, _a, allIds, allSubjects, loadRelationPropertyPaths, findOptions, entities, allSubjects_1, allSubjects_1_1, subject;
36 var _this = this;
37 return tslib_1.__generator(this, function (_b) {
38 switch (_b.label) {
39 case 0:
40 allIds = [];
41 allSubjects = [];
42 subjectGroup.subjects.forEach(function (subject) {
43 // we don't load if subject already has a database entity loaded
44 if (subject.databaseEntity || !subject.identifier)
45 return;
46 allIds.push(subject.identifier);
47 allSubjects.push(subject);
48 });
49 // if there no ids found (means all entities are new and have generated ids) - then nothing to load there
50 if (!allIds.length)
51 return [2 /*return*/];
52 loadRelationPropertyPaths = [];
53 // for the save operation
54 // extract all property paths of the relations we need to load relation ids for
55 // this is for optimization purpose - this way we don't load relation ids for entities
56 // whose relations are undefined, and since they are undefined its really pointless to
57 // load something for them, since undefined properties are skipped by the orm
58 if (operationType === "save") {
59 subjectGroup.subjects.forEach(function (subject) {
60 // gets all relation property paths that exist in the persisted entity.
61 subject.metadata.relations.forEach(function (relation) {
62 var value = relation.getEntityValue(subject.entityWithFulfilledIds);
63 if (value === undefined)
64 return;
65 if (loadRelationPropertyPaths.indexOf(relation.propertyPath) === -1)
66 loadRelationPropertyPaths.push(relation.propertyPath);
67 });
68 });
69 }
70 else { // remove
71 // for remove operation
72 // we only need to load junction relation ids since only they are removed by cascades
73 loadRelationPropertyPaths.push.apply(// remove
74 loadRelationPropertyPaths, tslib_1.__spread(subjectGroup.subjects[0].metadata.manyToManyRelations.map(function (relation) { return relation.propertyPath; })));
75 }
76 findOptions = {
77 loadEagerRelations: false,
78 loadRelationIds: {
79 relations: loadRelationPropertyPaths,
80 disableMixedMap: true
81 }
82 };
83 return [4 /*yield*/, this.queryRunner.manager
84 .getRepository(subjectGroup.target)
85 .findByIds(allIds, findOptions)];
86 case 1:
87 entities = _b.sent();
88 // now when we have entities we need to find subject of each entity
89 // and insert that entity into database entity of the found subjects
90 entities.forEach(function (entity) {
91 var subjects = _this.findByPersistEntityLike(subjectGroup.target, entity);
92 subjects.forEach(function (subject) {
93 subject.databaseEntity = entity;
94 if (!subject.identifier)
95 subject.identifier = subject.metadata.hasAllPrimaryKeys(entity) ? subject.metadata.getEntityIdMap(entity) : undefined;
96 });
97 });
98 try {
99 // this way we tell what subjects we tried to load database entities of
100 for (allSubjects_1 = tslib_1.__values(allSubjects), allSubjects_1_1 = allSubjects_1.next(); !allSubjects_1_1.done; allSubjects_1_1 = allSubjects_1.next()) {
101 subject = allSubjects_1_1.value;
102 subject.databaseEntityLoaded = true;
103 }
104 }
105 catch (e_1_1) { e_1 = { error: e_1_1 }; }
106 finally {
107 try {
108 if (allSubjects_1_1 && !allSubjects_1_1.done && (_a = allSubjects_1.return)) _a.call(allSubjects_1);
109 }
110 finally { if (e_1) throw e_1.error; }
111 }
112 return [2 /*return*/];
113 }
114 });
115 }); });
116 return [4 /*yield*/, Promise.all(promises)];
117 case 1:
118 _a.sent();
119 return [2 /*return*/];
120 }
121 });
122 });
123 };
124 // ---------------------------------------------------------------------
125 // Protected Methods
126 // ---------------------------------------------------------------------
127 /**
128 * Finds subjects where entity like given subject's entity.
129 * Comparision made by entity id.
130 * Multiple subjects may be returned if duplicates are present in the subject array.
131 * This will likely result in the same row being updated multiple times during a transaction.
132 */
133 SubjectDatabaseEntityLoader.prototype.findByPersistEntityLike = function (entityTarget, entity) {
134 return this.subjects.filter(function (subject) {
135 if (!subject.entity)
136 return false;
137 if (subject.entity === entity)
138 return true;
139 return subject.metadata.target === entityTarget && subject.metadata.compareEntities(subject.entityWithFulfilledIds, entity);
140 });
141 };
142 /**
143 * Groups given Subject objects into groups separated by entity targets.
144 */
145 SubjectDatabaseEntityLoader.prototype.groupByEntityTargets = function () {
146 return this.subjects.reduce(function (groups, operatedEntity) {
147 var group = groups.find(function (group) { return group.target === operatedEntity.metadata.target; });
148 if (!group) {
149 group = { target: operatedEntity.metadata.target, subjects: [] };
150 groups.push(group);
151 }
152 group.subjects.push(operatedEntity);
153 return groups;
154 }, []);
155 };
156 return SubjectDatabaseEntityLoader;
157}());
158exports.SubjectDatabaseEntityLoader = SubjectDatabaseEntityLoader;
159
160//# sourceMappingURL=SubjectDatabaseEntityLoader.js.map