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