@mikro-orm/core 7.0.0-rc.3 → 7.0.1-dev.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/EntityManager.d.ts +2 -15
- package/EntityManager.js +155 -152
- package/MikroORM.d.ts +4 -6
- package/MikroORM.js +20 -20
- package/README.md +5 -4
- package/cache/FileCacheAdapter.d.ts +1 -5
- package/cache/FileCacheAdapter.js +22 -22
- package/cache/GeneratedCacheAdapter.d.ts +1 -1
- package/cache/GeneratedCacheAdapter.js +6 -6
- package/cache/MemoryCacheAdapter.d.ts +1 -2
- package/cache/MemoryCacheAdapter.js +8 -8
- package/cache/index.d.ts +1 -1
- package/cache/index.js +0 -1
- package/connections/Connection.d.ts +1 -0
- package/connections/Connection.js +27 -11
- package/drivers/DatabaseDriver.d.ts +0 -2
- package/drivers/DatabaseDriver.js +2 -4
- package/entity/Collection.d.ts +1 -9
- package/entity/Collection.js +95 -105
- package/entity/EntityFactory.d.ts +1 -8
- package/entity/EntityFactory.js +48 -48
- package/entity/EntityLoader.d.ts +1 -3
- package/entity/EntityLoader.js +36 -39
- package/entity/Reference.d.ts +1 -2
- package/entity/Reference.js +11 -11
- package/entity/WrappedEntity.d.ts +4 -2
- package/entity/defineEntity.d.ts +18 -73
- package/enums.d.ts +2 -1
- package/enums.js +1 -0
- package/errors.d.ts +11 -11
- package/errors.js +3 -13
- package/events/EventManager.d.ts +1 -4
- package/events/EventManager.js +25 -22
- package/events/index.d.ts +1 -1
- package/events/index.js +0 -1
- package/exceptions.js +8 -6
- package/hydration/ObjectHydrator.d.ts +1 -2
- package/hydration/ObjectHydrator.js +16 -16
- package/logging/DefaultLogger.js +3 -2
- package/logging/Logger.d.ts +2 -1
- package/logging/colors.js +1 -1
- package/logging/index.d.ts +1 -1
- package/logging/index.js +0 -1
- package/metadata/EntitySchema.d.ts +1 -1
- package/metadata/MetadataDiscovery.d.ts +1 -9
- package/metadata/MetadataDiscovery.js +162 -149
- package/metadata/MetadataStorage.d.ts +1 -5
- package/metadata/MetadataStorage.js +36 -36
- package/metadata/discover-entities.js +1 -1
- package/metadata/index.d.ts +1 -1
- package/metadata/index.js +0 -1
- package/naming-strategy/AbstractNamingStrategy.js +1 -1
- package/naming-strategy/EntityCaseNamingStrategy.js +1 -1
- package/naming-strategy/index.d.ts +1 -1
- package/naming-strategy/index.js +0 -1
- package/package.json +1 -1
- package/platforms/Platform.d.ts +23 -1
- package/platforms/Platform.js +57 -4
- package/serialization/EntitySerializer.js +1 -1
- package/serialization/EntityTransformer.js +4 -1
- package/serialization/SerializationContext.d.ts +4 -8
- package/serialization/SerializationContext.js +20 -15
- package/types/UuidType.d.ts +2 -0
- package/types/UuidType.js +14 -2
- package/types/index.d.ts +2 -1
- package/typings.d.ts +12 -1
- package/unit-of-work/ChangeSetComputer.d.ts +1 -6
- package/unit-of-work/ChangeSetComputer.js +21 -21
- package/unit-of-work/ChangeSetPersister.d.ts +1 -9
- package/unit-of-work/ChangeSetPersister.js +52 -52
- package/unit-of-work/CommitOrderCalculator.d.ts +1 -4
- package/unit-of-work/CommitOrderCalculator.js +13 -13
- package/unit-of-work/IdentityMap.d.ts +2 -5
- package/unit-of-work/IdentityMap.js +18 -18
- package/unit-of-work/UnitOfWork.d.ts +5 -19
- package/unit-of-work/UnitOfWork.js +182 -174
- package/utils/AbstractMigrator.d.ts +1 -1
- package/utils/AbstractMigrator.js +7 -7
- package/utils/Configuration.d.ts +90 -189
- package/utils/Configuration.js +94 -78
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +4 -4
- package/utils/EntityComparator.d.ts +8 -15
- package/utils/EntityComparator.js +49 -49
- package/utils/QueryHelper.d.ts +16 -1
- package/utils/QueryHelper.js +70 -24
- package/utils/RawQueryFragment.d.ts +4 -4
- package/utils/TransactionManager.js +1 -2
- package/utils/Utils.d.ts +1 -1
- package/utils/Utils.js +5 -4
- package/utils/clone.js +5 -0
- package/utils/fs-utils.d.ts +3 -17
- package/utils/fs-utils.js +1 -1
- package/utils/upsert-utils.js +1 -1
|
@@ -16,38 +16,38 @@ import { createAsyncContext } from '../utils/AsyncContext.js';
|
|
|
16
16
|
// to deal with validation for flush inside flush hooks and `Promise.all`
|
|
17
17
|
const insideFlush = createAsyncContext();
|
|
18
18
|
export class UnitOfWork {
|
|
19
|
-
em;
|
|
20
19
|
/** map of references to managed entities */
|
|
21
|
-
identityMap;
|
|
22
|
-
persistStack = new Set();
|
|
23
|
-
removeStack = new Set();
|
|
24
|
-
orphanRemoveStack = new Set();
|
|
25
|
-
changeSets = new Map();
|
|
26
|
-
collectionUpdates = new Set();
|
|
27
|
-
extraUpdates = new Set();
|
|
28
|
-
metadata;
|
|
29
|
-
platform;
|
|
30
|
-
eventManager;
|
|
31
|
-
comparator;
|
|
32
|
-
changeSetComputer;
|
|
33
|
-
changeSetPersister;
|
|
34
|
-
queuedActions = new Set();
|
|
35
|
-
loadedEntities = new Set();
|
|
36
|
-
flushQueue = [];
|
|
37
|
-
working = false;
|
|
20
|
+
#identityMap;
|
|
21
|
+
#persistStack = new Set();
|
|
22
|
+
#removeStack = new Set();
|
|
23
|
+
#orphanRemoveStack = new Set();
|
|
24
|
+
#changeSets = new Map();
|
|
25
|
+
#collectionUpdates = new Set();
|
|
26
|
+
#extraUpdates = new Set();
|
|
27
|
+
#metadata;
|
|
28
|
+
#platform;
|
|
29
|
+
#eventManager;
|
|
30
|
+
#comparator;
|
|
31
|
+
#changeSetComputer;
|
|
32
|
+
#changeSetPersister;
|
|
33
|
+
#queuedActions = new Set();
|
|
34
|
+
#loadedEntities = new Set();
|
|
35
|
+
#flushQueue = [];
|
|
36
|
+
#working = false;
|
|
37
|
+
#em;
|
|
38
38
|
constructor(em) {
|
|
39
|
-
this
|
|
40
|
-
this
|
|
41
|
-
this
|
|
42
|
-
this
|
|
43
|
-
this
|
|
44
|
-
this
|
|
45
|
-
this
|
|
46
|
-
this
|
|
39
|
+
this.#em = em;
|
|
40
|
+
this.#metadata = this.#em.getMetadata();
|
|
41
|
+
this.#platform = this.#em.getPlatform();
|
|
42
|
+
this.#identityMap = new IdentityMap(this.#platform.getDefaultSchemaName());
|
|
43
|
+
this.#eventManager = this.#em.getEventManager();
|
|
44
|
+
this.#comparator = this.#em.getComparator();
|
|
45
|
+
this.#changeSetComputer = new ChangeSetComputer(this.#em, this.#collectionUpdates);
|
|
46
|
+
this.#changeSetPersister = new ChangeSetPersister(this.#em);
|
|
47
47
|
}
|
|
48
48
|
merge(entity, visited) {
|
|
49
49
|
const wrapped = helper(entity);
|
|
50
|
-
wrapped.__em = this
|
|
50
|
+
wrapped.__em = this.#em;
|
|
51
51
|
if (!wrapped.hasPrimaryKey()) {
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
@@ -56,11 +56,11 @@ export class UnitOfWork {
|
|
|
56
56
|
if (!wrapped.__managed && visited) {
|
|
57
57
|
return;
|
|
58
58
|
}
|
|
59
|
-
this
|
|
59
|
+
this.#identityMap.store(entity);
|
|
60
60
|
// if visited is available, we are cascading, and need to be careful when resetting the entity data
|
|
61
61
|
// as there can be some entity with already changed state that is not yet flushed
|
|
62
62
|
if (wrapped.__initialized && (!visited || !wrapped.__originalEntityData)) {
|
|
63
|
-
wrapped.__originalEntityData = this
|
|
63
|
+
wrapped.__originalEntityData = this.#comparator.prepareEntity(entity);
|
|
64
64
|
}
|
|
65
65
|
this.cascade(entity, Cascade.MERGE, visited ?? new Set());
|
|
66
66
|
}
|
|
@@ -70,7 +70,7 @@ export class UnitOfWork {
|
|
|
70
70
|
* @internal
|
|
71
71
|
*/
|
|
72
72
|
normalizeEntityData(meta, data) {
|
|
73
|
-
const forceUndefined = this
|
|
73
|
+
const forceUndefined = this.#em.config.get('forceUndefined');
|
|
74
74
|
for (const key of Utils.keys(data)) {
|
|
75
75
|
const prop = meta.properties[key];
|
|
76
76
|
if (!prop) {
|
|
@@ -92,12 +92,12 @@ export class UnitOfWork {
|
|
|
92
92
|
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
93
93
|
}
|
|
94
94
|
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
95
|
-
const converted = prop.customType.convertToJSValue(data[key], this
|
|
95
|
+
const converted = prop.customType.convertToJSValue(data[key], this.#platform, {
|
|
96
96
|
key,
|
|
97
97
|
mode: 'hydration',
|
|
98
98
|
force: true,
|
|
99
99
|
});
|
|
100
|
-
data[key] = prop.customType.convertToDatabaseValue(converted, this
|
|
100
|
+
data[key] = prop.customType.convertToDatabaseValue(converted, this.#platform, { key, mode: 'hydration' });
|
|
101
101
|
}
|
|
102
102
|
if (forceUndefined) {
|
|
103
103
|
if (data[key] === null) {
|
|
@@ -110,17 +110,17 @@ export class UnitOfWork {
|
|
|
110
110
|
* @internal
|
|
111
111
|
*/
|
|
112
112
|
register(entity, data, options) {
|
|
113
|
-
this
|
|
113
|
+
this.#identityMap.store(entity);
|
|
114
114
|
EntityHelper.ensurePropagation(entity);
|
|
115
115
|
if (options?.newEntity) {
|
|
116
116
|
return entity;
|
|
117
117
|
}
|
|
118
|
-
const forceUndefined = this
|
|
118
|
+
const forceUndefined = this.#em.config.get('forceUndefined');
|
|
119
119
|
const wrapped = helper(entity);
|
|
120
120
|
if (options?.loaded && wrapped.__initialized && !wrapped.__onLoadFired) {
|
|
121
|
-
this
|
|
121
|
+
this.#loadedEntities.add(entity);
|
|
122
122
|
}
|
|
123
|
-
wrapped.__em ??= this
|
|
123
|
+
wrapped.__em ??= this.#em;
|
|
124
124
|
wrapped.__managed = true;
|
|
125
125
|
if (data && (options?.refresh || !wrapped.__originalEntityData)) {
|
|
126
126
|
this.normalizeEntityData(wrapped.__meta, data);
|
|
@@ -138,13 +138,19 @@ export class UnitOfWork {
|
|
|
138
138
|
* @internal
|
|
139
139
|
*/
|
|
140
140
|
async dispatchOnLoadEvent() {
|
|
141
|
-
for (const entity of this
|
|
142
|
-
if (this
|
|
143
|
-
await this
|
|
141
|
+
for (const entity of this.#loadedEntities) {
|
|
142
|
+
if (this.#eventManager.hasListeners(EventType.onLoad, entity.__meta)) {
|
|
143
|
+
await this.#eventManager.dispatchEvent(EventType.onLoad, { entity, meta: entity.__meta, em: this.#em });
|
|
144
144
|
helper(entity).__onLoadFired = true;
|
|
145
145
|
}
|
|
146
146
|
}
|
|
147
|
-
this
|
|
147
|
+
this.#loadedEntities.clear();
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* @internal
|
|
151
|
+
*/
|
|
152
|
+
unmarkAsLoaded(entity) {
|
|
153
|
+
this.#loadedEntities.delete(entity);
|
|
148
154
|
}
|
|
149
155
|
/**
|
|
150
156
|
* Returns entity from the identity map. For composite keys, you need to pass an array of PKs in the same order as they are defined in `meta.primaryKeys`.
|
|
@@ -153,7 +159,7 @@ export class UnitOfWork {
|
|
|
153
159
|
if (id == null || (Array.isArray(id) && id.length === 0)) {
|
|
154
160
|
return undefined;
|
|
155
161
|
}
|
|
156
|
-
const meta = this
|
|
162
|
+
const meta = this.#metadata.find(entityName).root;
|
|
157
163
|
let hash;
|
|
158
164
|
if (meta.simplePK) {
|
|
159
165
|
hash = '' + id;
|
|
@@ -162,7 +168,7 @@ export class UnitOfWork {
|
|
|
162
168
|
let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
|
|
163
169
|
keys = meta.getPrimaryProps(true).map((p, i) => {
|
|
164
170
|
if (!convertCustomTypes && p.customType) {
|
|
165
|
-
return p.customType.convertToDatabaseValue(keys[i], this
|
|
171
|
+
return p.customType.convertToDatabaseValue(keys[i], this.#platform, {
|
|
166
172
|
key: p.name,
|
|
167
173
|
mode: 'hydration',
|
|
168
174
|
});
|
|
@@ -171,11 +177,11 @@ export class UnitOfWork {
|
|
|
171
177
|
});
|
|
172
178
|
hash = Utils.getPrimaryKeyHash(keys);
|
|
173
179
|
}
|
|
174
|
-
schema ??= meta.schema ?? this
|
|
180
|
+
schema ??= meta.schema ?? this.#em.config.getSchema();
|
|
175
181
|
if (schema) {
|
|
176
182
|
hash = `${schema}:${hash}`;
|
|
177
183
|
}
|
|
178
|
-
return this
|
|
184
|
+
return this.#identityMap.getByHash(meta, hash);
|
|
179
185
|
}
|
|
180
186
|
/**
|
|
181
187
|
* Returns entity from the identity map by an alternate key (non-PK property).
|
|
@@ -183,15 +189,15 @@ export class UnitOfWork {
|
|
|
183
189
|
* If false (default), the value is assumed to be in JS format already.
|
|
184
190
|
*/
|
|
185
191
|
getByKey(entityName, key, value, schema, convertCustomTypes) {
|
|
186
|
-
const meta = this
|
|
187
|
-
schema ??= meta.schema ?? this
|
|
192
|
+
const meta = this.#metadata.find(entityName).root;
|
|
193
|
+
schema ??= meta.schema ?? this.#em.config.getSchema();
|
|
188
194
|
const prop = meta.properties[key];
|
|
189
195
|
// Convert from DB format to JS format if needed
|
|
190
196
|
if (convertCustomTypes && prop?.customType) {
|
|
191
|
-
value = prop.customType.convertToJSValue(value, this
|
|
197
|
+
value = prop.customType.convertToJSValue(value, this.#platform, { mode: 'hydration' });
|
|
192
198
|
}
|
|
193
|
-
const hash = this
|
|
194
|
-
return this
|
|
199
|
+
const hash = this.#identityMap.getKeyHash(key, '' + value, schema);
|
|
200
|
+
return this.#identityMap.getByHash(meta, hash);
|
|
195
201
|
}
|
|
196
202
|
/**
|
|
197
203
|
* Stores an entity in the identity map under an alternate key (non-PK property).
|
|
@@ -201,18 +207,18 @@ export class UnitOfWork {
|
|
|
201
207
|
*/
|
|
202
208
|
storeByKey(entity, key, value, schema, convertCustomTypes) {
|
|
203
209
|
const meta = entity.__meta.root;
|
|
204
|
-
schema ??= meta.schema ?? this
|
|
210
|
+
schema ??= meta.schema ?? this.#em.config.getSchema();
|
|
205
211
|
const prop = meta.properties[key];
|
|
206
212
|
// Convert from DB format to JS format if needed
|
|
207
213
|
if (convertCustomTypes && prop?.customType) {
|
|
208
|
-
value = prop.customType.convertToJSValue(value, this
|
|
214
|
+
value = prop.customType.convertToJSValue(value, this.#platform, { mode: 'hydration' });
|
|
209
215
|
}
|
|
210
216
|
// Set the property on the entity
|
|
211
217
|
entity[key] = value;
|
|
212
|
-
this
|
|
218
|
+
this.#identityMap.storeByKey(entity, key, '' + value, schema);
|
|
213
219
|
}
|
|
214
220
|
tryGetById(entityName, where, schema, strict = true) {
|
|
215
|
-
const pk = Utils.extractPK(where, this
|
|
221
|
+
const pk = Utils.extractPK(where, this.#metadata.find(entityName), strict);
|
|
216
222
|
if (!pk) {
|
|
217
223
|
return null;
|
|
218
224
|
}
|
|
@@ -222,7 +228,7 @@ export class UnitOfWork {
|
|
|
222
228
|
* Returns map of all managed entities.
|
|
223
229
|
*/
|
|
224
230
|
getIdentityMap() {
|
|
225
|
-
return this
|
|
231
|
+
return this.#identityMap;
|
|
226
232
|
}
|
|
227
233
|
/**
|
|
228
234
|
* Returns stored snapshot of entity state that is used for change set computation.
|
|
@@ -231,42 +237,42 @@ export class UnitOfWork {
|
|
|
231
237
|
return helper(entity).__originalEntityData;
|
|
232
238
|
}
|
|
233
239
|
getPersistStack() {
|
|
234
|
-
return this
|
|
240
|
+
return this.#persistStack;
|
|
235
241
|
}
|
|
236
242
|
getRemoveStack() {
|
|
237
|
-
return this
|
|
243
|
+
return this.#removeStack;
|
|
238
244
|
}
|
|
239
245
|
getChangeSets() {
|
|
240
|
-
return [...this
|
|
246
|
+
return [...this.#changeSets.values()];
|
|
241
247
|
}
|
|
242
248
|
getCollectionUpdates() {
|
|
243
|
-
return [...this
|
|
249
|
+
return [...this.#collectionUpdates];
|
|
244
250
|
}
|
|
245
251
|
getExtraUpdates() {
|
|
246
|
-
return this
|
|
252
|
+
return this.#extraUpdates;
|
|
247
253
|
}
|
|
248
254
|
shouldAutoFlush(meta) {
|
|
249
255
|
if (insideFlush.getStore()) {
|
|
250
256
|
return false;
|
|
251
257
|
}
|
|
252
|
-
if (this
|
|
258
|
+
if (this.#queuedActions.has(meta.class) || this.#queuedActions.has(meta.root.class)) {
|
|
253
259
|
return true;
|
|
254
260
|
}
|
|
255
|
-
if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this
|
|
261
|
+
if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this.#queuedActions.has(v))) {
|
|
256
262
|
return true;
|
|
257
263
|
}
|
|
258
264
|
return false;
|
|
259
265
|
}
|
|
260
266
|
clearActionsQueue() {
|
|
261
|
-
this
|
|
267
|
+
this.#queuedActions.clear();
|
|
262
268
|
}
|
|
263
269
|
computeChangeSet(entity, type) {
|
|
264
270
|
const wrapped = helper(entity);
|
|
265
271
|
if (type === ChangeSetType.DELETE || type === ChangeSetType.DELETE_EARLY) {
|
|
266
|
-
this
|
|
272
|
+
this.#changeSets.set(entity, new ChangeSet(entity, type, {}, wrapped.__meta));
|
|
267
273
|
return;
|
|
268
274
|
}
|
|
269
|
-
const cs = this
|
|
275
|
+
const cs = this.#changeSetComputer.computeChangeSet(entity);
|
|
270
276
|
if (!cs || this.checkUniqueProps(cs)) {
|
|
271
277
|
return;
|
|
272
278
|
}
|
|
@@ -275,32 +281,32 @@ export class UnitOfWork {
|
|
|
275
281
|
cs.type = type;
|
|
276
282
|
}
|
|
277
283
|
this.initIdentifier(entity);
|
|
278
|
-
this
|
|
279
|
-
this
|
|
280
|
-
wrapped.__originalEntityData = this
|
|
284
|
+
this.#changeSets.set(entity, cs);
|
|
285
|
+
this.#persistStack.delete(entity);
|
|
286
|
+
wrapped.__originalEntityData = this.#comparator.prepareEntity(entity);
|
|
281
287
|
}
|
|
282
288
|
recomputeSingleChangeSet(entity) {
|
|
283
|
-
const changeSet = this
|
|
289
|
+
const changeSet = this.#changeSets.get(entity);
|
|
284
290
|
if (!changeSet) {
|
|
285
291
|
return;
|
|
286
292
|
}
|
|
287
|
-
const cs = this
|
|
293
|
+
const cs = this.#changeSetComputer.computeChangeSet(entity);
|
|
288
294
|
if (cs && !this.checkUniqueProps(cs)) {
|
|
289
295
|
Object.assign(changeSet.payload, cs.payload);
|
|
290
|
-
helper(entity).__originalEntityData = this
|
|
296
|
+
helper(entity).__originalEntityData = this.#comparator.prepareEntity(entity);
|
|
291
297
|
}
|
|
292
298
|
}
|
|
293
299
|
persist(entity, visited, options = {}) {
|
|
294
300
|
EntityHelper.ensurePropagation(entity);
|
|
295
|
-
if (options.checkRemoveStack && this
|
|
301
|
+
if (options.checkRemoveStack && this.#removeStack.has(entity)) {
|
|
296
302
|
return;
|
|
297
303
|
}
|
|
298
304
|
const wrapped = helper(entity);
|
|
299
|
-
this
|
|
300
|
-
this
|
|
301
|
-
this
|
|
305
|
+
this.#persistStack.add(entity);
|
|
306
|
+
this.#queuedActions.add(wrapped.__meta.class);
|
|
307
|
+
this.#removeStack.delete(entity);
|
|
302
308
|
if (!wrapped.__managed && wrapped.hasPrimaryKey()) {
|
|
303
|
-
this
|
|
309
|
+
this.#identityMap.store(entity);
|
|
304
310
|
}
|
|
305
311
|
if (options.cascade ?? true) {
|
|
306
312
|
this.cascade(entity, Cascade.PERSIST, visited, options);
|
|
@@ -308,13 +314,13 @@ export class UnitOfWork {
|
|
|
308
314
|
}
|
|
309
315
|
remove(entity, visited, options = {}) {
|
|
310
316
|
// allow removing not managed entities if they are not part of the persist stack
|
|
311
|
-
if (helper(entity).__managed || !this
|
|
312
|
-
this
|
|
313
|
-
this
|
|
317
|
+
if (helper(entity).__managed || !this.#persistStack.has(entity)) {
|
|
318
|
+
this.#removeStack.add(entity);
|
|
319
|
+
this.#queuedActions.add(helper(entity).__meta.class);
|
|
314
320
|
}
|
|
315
321
|
else {
|
|
316
|
-
this
|
|
317
|
-
this
|
|
322
|
+
this.#persistStack.delete(entity);
|
|
323
|
+
this.#identityMap.delete(entity);
|
|
318
324
|
}
|
|
319
325
|
// remove from referencing relations that are nullable
|
|
320
326
|
for (const prop of helper(entity).__meta.bidirectionalRelations) {
|
|
@@ -327,7 +333,7 @@ export class UnitOfWork {
|
|
|
327
333
|
}
|
|
328
334
|
continue;
|
|
329
335
|
}
|
|
330
|
-
const target = relation
|
|
336
|
+
const target = relation?.[inverseProp];
|
|
331
337
|
if (relation && Utils.isCollection(target)) {
|
|
332
338
|
target.removeWithoutPropagation(entity);
|
|
333
339
|
}
|
|
@@ -337,12 +343,12 @@ export class UnitOfWork {
|
|
|
337
343
|
}
|
|
338
344
|
}
|
|
339
345
|
async commit() {
|
|
340
|
-
if (this
|
|
346
|
+
if (this.#working) {
|
|
341
347
|
if (insideFlush.getStore()) {
|
|
342
348
|
throw ValidationError.cannotCommit();
|
|
343
349
|
}
|
|
344
350
|
return new Promise((resolve, reject) => {
|
|
345
|
-
this
|
|
351
|
+
this.#flushQueue.push(() => {
|
|
346
352
|
return insideFlush.run(true, () => {
|
|
347
353
|
return this.doCommit().then(resolve, reject);
|
|
348
354
|
});
|
|
@@ -350,51 +356,51 @@ export class UnitOfWork {
|
|
|
350
356
|
});
|
|
351
357
|
}
|
|
352
358
|
try {
|
|
353
|
-
this
|
|
359
|
+
this.#working = true;
|
|
354
360
|
await insideFlush.run(true, () => this.doCommit());
|
|
355
|
-
while (this
|
|
356
|
-
await this
|
|
361
|
+
while (this.#flushQueue.length) {
|
|
362
|
+
await this.#flushQueue.shift()();
|
|
357
363
|
}
|
|
358
364
|
}
|
|
359
365
|
finally {
|
|
360
366
|
this.postCommitCleanup();
|
|
361
|
-
this
|
|
367
|
+
this.#working = false;
|
|
362
368
|
}
|
|
363
369
|
}
|
|
364
370
|
async doCommit() {
|
|
365
|
-
const oldTx = this
|
|
371
|
+
const oldTx = this.#em.getTransactionContext();
|
|
366
372
|
try {
|
|
367
|
-
await this
|
|
373
|
+
await this.#eventManager.dispatchEvent(EventType.beforeFlush, { em: this.#em, uow: this });
|
|
368
374
|
this.computeChangeSets();
|
|
369
|
-
for (const cs of this
|
|
375
|
+
for (const cs of this.#changeSets.values()) {
|
|
370
376
|
cs.entity.__helper.__processing = true;
|
|
371
377
|
}
|
|
372
|
-
await this
|
|
378
|
+
await this.#eventManager.dispatchEvent(EventType.onFlush, { em: this.#em, uow: this });
|
|
373
379
|
this.filterCollectionUpdates();
|
|
374
380
|
// nothing to do, do not start transaction
|
|
375
|
-
if (this
|
|
376
|
-
await this
|
|
381
|
+
if (this.#changeSets.size === 0 && this.#collectionUpdates.size === 0 && this.#extraUpdates.size === 0) {
|
|
382
|
+
await this.#eventManager.dispatchEvent(EventType.afterFlush, { em: this.#em, uow: this });
|
|
377
383
|
return;
|
|
378
384
|
}
|
|
379
385
|
const groups = this.getChangeSetGroups();
|
|
380
|
-
const platform = this
|
|
381
|
-
const runInTransaction = !this
|
|
386
|
+
const platform = this.#em.getPlatform();
|
|
387
|
+
const runInTransaction = !this.#em.isInTransaction() && platform.supportsTransactions() && this.#em.config.get('implicitTransactions');
|
|
382
388
|
if (runInTransaction) {
|
|
383
|
-
const loggerContext = Utils.merge({ id: this
|
|
384
|
-
await this
|
|
389
|
+
const loggerContext = Utils.merge({ id: this.#em._id }, this.#em.getLoggerContext({ disableContextResolution: true }));
|
|
390
|
+
await this.#em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
|
|
385
391
|
ctx: oldTx,
|
|
386
|
-
eventBroadcaster: new TransactionEventBroadcaster(this
|
|
392
|
+
eventBroadcaster: new TransactionEventBroadcaster(this.#em),
|
|
387
393
|
loggerContext,
|
|
388
394
|
});
|
|
389
395
|
}
|
|
390
396
|
else {
|
|
391
|
-
await this.persistToDatabase(groups, this
|
|
397
|
+
await this.persistToDatabase(groups, this.#em.getTransactionContext());
|
|
392
398
|
}
|
|
393
399
|
this.resetTransaction(oldTx);
|
|
394
|
-
for (const cs of this
|
|
400
|
+
for (const cs of this.#changeSets.values()) {
|
|
395
401
|
cs.entity.__helper.__processing = false;
|
|
396
402
|
}
|
|
397
|
-
await this
|
|
403
|
+
await this.#eventManager.dispatchEvent(EventType.afterFlush, { em: this.#em, uow: this });
|
|
398
404
|
}
|
|
399
405
|
finally {
|
|
400
406
|
this.resetTransaction(oldTx);
|
|
@@ -404,7 +410,7 @@ export class UnitOfWork {
|
|
|
404
410
|
if (!this.getById(entity.constructor, helper(entity).__primaryKeys, helper(entity).__schema)) {
|
|
405
411
|
throw ValidationError.entityNotManaged(entity);
|
|
406
412
|
}
|
|
407
|
-
const meta = this
|
|
413
|
+
const meta = this.#metadata.find(entity.constructor);
|
|
408
414
|
if (options.lockMode === LockMode.OPTIMISTIC) {
|
|
409
415
|
await this.lockOptimistic(entity, meta, options.lockVersion);
|
|
410
416
|
}
|
|
@@ -413,24 +419,24 @@ export class UnitOfWork {
|
|
|
413
419
|
}
|
|
414
420
|
}
|
|
415
421
|
clear() {
|
|
416
|
-
this
|
|
417
|
-
this
|
|
422
|
+
this.#identityMap.clear();
|
|
423
|
+
this.#loadedEntities.clear();
|
|
418
424
|
this.postCommitCleanup();
|
|
419
425
|
}
|
|
420
426
|
unsetIdentity(entity) {
|
|
421
|
-
this
|
|
427
|
+
this.#identityMap.delete(entity);
|
|
422
428
|
const wrapped = helper(entity);
|
|
423
429
|
const serializedPK = wrapped.getSerializedPrimaryKey();
|
|
424
430
|
// remove references of this entity in all managed entities, otherwise flushing could reinsert the entity
|
|
425
431
|
for (const { meta, prop } of wrapped.__meta.referencingProperties) {
|
|
426
|
-
for (const referrer of this
|
|
432
|
+
for (const referrer of this.#identityMap.getStore(meta).values()) {
|
|
427
433
|
const rel = Reference.unwrapReference(referrer[prop.name]);
|
|
428
434
|
if (Utils.isCollection(rel)) {
|
|
429
435
|
rel.removeWithoutPropagation(entity);
|
|
430
436
|
}
|
|
431
437
|
else if (rel &&
|
|
432
438
|
(prop.mapToPk
|
|
433
|
-
? helper(this
|
|
439
|
+
? helper(this.#em.getReference(prop.targetMeta.class, rel)).getSerializedPrimaryKey() === serializedPK
|
|
434
440
|
: rel === entity)) {
|
|
435
441
|
if (prop.formula) {
|
|
436
442
|
delete referrer[prop.name];
|
|
@@ -446,43 +452,43 @@ export class UnitOfWork {
|
|
|
446
452
|
wrapped.__managed = false;
|
|
447
453
|
}
|
|
448
454
|
computeChangeSets() {
|
|
449
|
-
this
|
|
455
|
+
this.#changeSets.clear();
|
|
450
456
|
const visited = new Set();
|
|
451
|
-
for (const entity of this
|
|
457
|
+
for (const entity of this.#removeStack) {
|
|
452
458
|
this.cascade(entity, Cascade.REMOVE, visited);
|
|
453
459
|
}
|
|
454
460
|
visited.clear();
|
|
455
|
-
for (const entity of this
|
|
456
|
-
if (!this
|
|
461
|
+
for (const entity of this.#identityMap) {
|
|
462
|
+
if (!this.#removeStack.has(entity) && !this.#persistStack.has(entity) && !this.#orphanRemoveStack.has(entity)) {
|
|
457
463
|
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
458
464
|
}
|
|
459
465
|
}
|
|
460
|
-
for (const entity of this
|
|
466
|
+
for (const entity of this.#persistStack) {
|
|
461
467
|
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
462
468
|
}
|
|
463
469
|
visited.clear();
|
|
464
|
-
for (const entity of this
|
|
470
|
+
for (const entity of this.#persistStack) {
|
|
465
471
|
this.findNewEntities(entity, visited);
|
|
466
472
|
}
|
|
467
|
-
for (const entity of this
|
|
473
|
+
for (const entity of this.#orphanRemoveStack) {
|
|
468
474
|
if (!helper(entity).__processing) {
|
|
469
|
-
this
|
|
475
|
+
this.#removeStack.add(entity);
|
|
470
476
|
}
|
|
471
477
|
}
|
|
472
478
|
// Check insert stack if there are any entities matching something from delete stack. This can happen when recreating entities.
|
|
473
479
|
const inserts = {};
|
|
474
|
-
for (const cs of this
|
|
480
|
+
for (const cs of this.#changeSets.values()) {
|
|
475
481
|
if (cs.type === ChangeSetType.CREATE) {
|
|
476
482
|
inserts[cs.meta.uniqueName] ??= [];
|
|
477
483
|
inserts[cs.meta.uniqueName].push(cs);
|
|
478
484
|
}
|
|
479
485
|
}
|
|
480
|
-
for (const cs of this
|
|
486
|
+
for (const cs of this.#changeSets.values()) {
|
|
481
487
|
if (cs.type === ChangeSetType.UPDATE) {
|
|
482
488
|
this.findEarlyUpdates(cs, inserts[cs.meta.uniqueName]);
|
|
483
489
|
}
|
|
484
490
|
}
|
|
485
|
-
for (const entity of this
|
|
491
|
+
for (const entity of this.#removeStack) {
|
|
486
492
|
const wrapped = helper(entity);
|
|
487
493
|
/* v8 ignore next */
|
|
488
494
|
if (wrapped.__processing) {
|
|
@@ -507,7 +513,7 @@ export class UnitOfWork {
|
|
|
507
513
|
if (!props.some(prop => prop.name in changeSet.payload)) {
|
|
508
514
|
return;
|
|
509
515
|
}
|
|
510
|
-
for (const cs of this
|
|
516
|
+
for (const cs of this.#changeSets.values()) {
|
|
511
517
|
for (const prop of props) {
|
|
512
518
|
if (prop.name in cs.payload && cs.rootMeta === changeSet.rootMeta && cs.type === changeSet.type) {
|
|
513
519
|
conflicts = true;
|
|
@@ -520,7 +526,7 @@ export class UnitOfWork {
|
|
|
520
526
|
if (!conflicts) {
|
|
521
527
|
return;
|
|
522
528
|
}
|
|
523
|
-
this
|
|
529
|
+
this.#extraUpdates.add([
|
|
524
530
|
changeSet.entity,
|
|
525
531
|
props.map(p => p.name),
|
|
526
532
|
props.map(p => changeSet.entity[p.name]),
|
|
@@ -535,21 +541,21 @@ export class UnitOfWork {
|
|
|
535
541
|
scheduleOrphanRemoval(entity, visited) {
|
|
536
542
|
if (entity) {
|
|
537
543
|
const wrapped = helper(entity);
|
|
538
|
-
wrapped.__em = this
|
|
539
|
-
this
|
|
540
|
-
this
|
|
544
|
+
wrapped.__em = this.#em;
|
|
545
|
+
this.#orphanRemoveStack.add(entity);
|
|
546
|
+
this.#queuedActions.add(wrapped.__meta.class);
|
|
541
547
|
this.cascade(entity, Cascade.SCHEDULE_ORPHAN_REMOVAL, visited);
|
|
542
548
|
}
|
|
543
549
|
}
|
|
544
550
|
cancelOrphanRemoval(entity, visited) {
|
|
545
|
-
this
|
|
551
|
+
this.#orphanRemoveStack.delete(entity);
|
|
546
552
|
this.cascade(entity, Cascade.CANCEL_ORPHAN_REMOVAL, visited);
|
|
547
553
|
}
|
|
548
554
|
getOrphanRemoveStack() {
|
|
549
|
-
return this
|
|
555
|
+
return this.#orphanRemoveStack;
|
|
550
556
|
}
|
|
551
557
|
getChangeSetPersister() {
|
|
552
|
-
return this
|
|
558
|
+
return this.#changeSetPersister;
|
|
553
559
|
}
|
|
554
560
|
findNewEntities(entity, visited, idx = 0, processed = new Set()) {
|
|
555
561
|
if (visited.has(entity)) {
|
|
@@ -558,11 +564,11 @@ export class UnitOfWork {
|
|
|
558
564
|
visited.add(entity);
|
|
559
565
|
processed.add(entity);
|
|
560
566
|
const wrapped = helper(entity);
|
|
561
|
-
if (wrapped.__processing || this
|
|
567
|
+
if (wrapped.__processing || this.#removeStack.has(entity) || this.#orphanRemoveStack.has(entity)) {
|
|
562
568
|
return;
|
|
563
569
|
}
|
|
564
570
|
// Set entityManager default schema
|
|
565
|
-
wrapped.__schema ??= this
|
|
571
|
+
wrapped.__schema ??= this.#em.schema;
|
|
566
572
|
this.initIdentifier(entity);
|
|
567
573
|
for (const prop of wrapped.__meta.relations) {
|
|
568
574
|
const targets = Utils.unwrapProperty(entity, wrapped.__meta, prop);
|
|
@@ -571,14 +577,14 @@ export class UnitOfWork {
|
|
|
571
577
|
this.processReference(entity, prop, kind, visited, processed, idx);
|
|
572
578
|
}
|
|
573
579
|
}
|
|
574
|
-
const changeSet = this
|
|
580
|
+
const changeSet = this.#changeSetComputer.computeChangeSet(entity);
|
|
575
581
|
if (changeSet && !this.checkUniqueProps(changeSet)) {
|
|
576
582
|
// For TPT child entities, create changesets for each table in hierarchy
|
|
577
583
|
if (wrapped.__meta.inheritanceType === 'tpt' && wrapped.__meta.tptParent) {
|
|
578
584
|
this.createTPTChangeSets(entity, changeSet);
|
|
579
585
|
}
|
|
580
586
|
else {
|
|
581
|
-
this
|
|
587
|
+
this.#changeSets.set(entity, changeSet);
|
|
582
588
|
}
|
|
583
589
|
}
|
|
584
590
|
}
|
|
@@ -634,7 +640,7 @@ export class UnitOfWork {
|
|
|
634
640
|
if (parentChangeSets.length > 0) {
|
|
635
641
|
leafCs.tptChangeSets = parentChangeSets;
|
|
636
642
|
}
|
|
637
|
-
this
|
|
643
|
+
this.#changeSets.set(entity, leafCs);
|
|
638
644
|
}
|
|
639
645
|
}
|
|
640
646
|
/**
|
|
@@ -734,7 +740,7 @@ export class UnitOfWork {
|
|
|
734
740
|
}
|
|
735
741
|
processToManyReference(collection, visited, processed, parent, prop) {
|
|
736
742
|
if (this.isCollectionSelfReferenced(collection, processed)) {
|
|
737
|
-
this
|
|
743
|
+
this.#extraUpdates.add([parent, prop.name, collection, undefined, ChangeSetType.UPDATE]);
|
|
738
744
|
const coll = new Collection(parent);
|
|
739
745
|
coll.property = prop;
|
|
740
746
|
parent[prop.name] = coll;
|
|
@@ -747,17 +753,17 @@ export class UnitOfWork {
|
|
|
747
753
|
}
|
|
748
754
|
async runHooks(type, changeSet, sync = false) {
|
|
749
755
|
const meta = changeSet.meta;
|
|
750
|
-
if (!this
|
|
756
|
+
if (!this.#eventManager.hasListeners(type, meta)) {
|
|
751
757
|
return;
|
|
752
758
|
}
|
|
753
759
|
if (!sync) {
|
|
754
|
-
await this
|
|
760
|
+
await this.#eventManager.dispatchEvent(type, { entity: changeSet.entity, meta, em: this.#em, changeSet });
|
|
755
761
|
return;
|
|
756
762
|
}
|
|
757
|
-
const copy = this
|
|
758
|
-
await this
|
|
759
|
-
const current = this
|
|
760
|
-
const diff = this
|
|
763
|
+
const copy = this.#comparator.prepareEntity(changeSet.entity);
|
|
764
|
+
await this.#eventManager.dispatchEvent(type, { entity: changeSet.entity, meta, em: this.#em, changeSet });
|
|
765
|
+
const current = this.#comparator.prepareEntity(changeSet.entity);
|
|
766
|
+
const diff = this.#comparator.diffEntities(changeSet.meta.class, copy, current);
|
|
761
767
|
Object.assign(changeSet.payload, diff);
|
|
762
768
|
const wrapped = helper(changeSet.entity);
|
|
763
769
|
if (wrapped.__identifier) {
|
|
@@ -772,19 +778,19 @@ export class UnitOfWork {
|
|
|
772
778
|
}
|
|
773
779
|
}
|
|
774
780
|
postCommitCleanup() {
|
|
775
|
-
for (const cs of this
|
|
781
|
+
for (const cs of this.#changeSets.values()) {
|
|
776
782
|
const wrapped = helper(cs.entity);
|
|
777
783
|
wrapped.__processing = false;
|
|
778
784
|
delete wrapped.__pk;
|
|
779
785
|
}
|
|
780
|
-
this
|
|
781
|
-
this
|
|
782
|
-
this
|
|
783
|
-
this
|
|
784
|
-
this
|
|
785
|
-
this
|
|
786
|
-
this
|
|
787
|
-
this
|
|
786
|
+
this.#persistStack.clear();
|
|
787
|
+
this.#removeStack.clear();
|
|
788
|
+
this.#orphanRemoveStack.clear();
|
|
789
|
+
this.#changeSets.clear();
|
|
790
|
+
this.#collectionUpdates.clear();
|
|
791
|
+
this.#extraUpdates.clear();
|
|
792
|
+
this.#queuedActions.clear();
|
|
793
|
+
this.#working = false;
|
|
788
794
|
}
|
|
789
795
|
cascade(entity, type, visited = new Set(), options = {}) {
|
|
790
796
|
if (visited.has(entity)) {
|
|
@@ -844,10 +850,10 @@ export class UnitOfWork {
|
|
|
844
850
|
return prop.cascade && (prop.cascade.includes(type) || prop.cascade.includes(Cascade.ALL));
|
|
845
851
|
}
|
|
846
852
|
async lockPessimistic(entity, options) {
|
|
847
|
-
if (!this
|
|
853
|
+
if (!this.#em.isInTransaction()) {
|
|
848
854
|
throw ValidationError.transactionRequired();
|
|
849
855
|
}
|
|
850
|
-
await this
|
|
856
|
+
await this.#em.getDriver().lockPessimistic(entity, { ctx: this.#em.getTransactionContext(), ...options });
|
|
851
857
|
}
|
|
852
858
|
async lockOptimistic(entity, meta, version) {
|
|
853
859
|
if (!meta.versionProperty) {
|
|
@@ -870,13 +876,15 @@ export class UnitOfWork {
|
|
|
870
876
|
const target = Reference.unwrapReference(reference);
|
|
871
877
|
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && target && !prop.mapToPk) {
|
|
872
878
|
if (!Utils.isEntity(target)) {
|
|
873
|
-
entity[prop.name] = this
|
|
879
|
+
entity[prop.name] = this.#em.getReference(prop.targetMeta.class, target, {
|
|
874
880
|
wrapped: !!prop.ref,
|
|
875
881
|
});
|
|
876
882
|
}
|
|
877
883
|
else if (!helper(target).__initialized && !helper(target).__em) {
|
|
878
884
|
const pk = helper(target).getPrimaryKey();
|
|
879
|
-
entity[prop.name] = this
|
|
885
|
+
entity[prop.name] = this.#em.getReference(prop.targetMeta.class, pk, {
|
|
886
|
+
wrapped: !!prop.ref,
|
|
887
|
+
});
|
|
880
888
|
}
|
|
881
889
|
}
|
|
882
890
|
// perf: set the `Collection._property` to skip the getter, as it can be slow when there are a lot of relations
|
|
@@ -893,7 +901,7 @@ export class UnitOfWork {
|
|
|
893
901
|
}
|
|
894
902
|
async persistToDatabase(groups, ctx) {
|
|
895
903
|
if (ctx) {
|
|
896
|
-
this
|
|
904
|
+
this.#em.setTransactionContext(ctx);
|
|
897
905
|
}
|
|
898
906
|
const commitOrder = this.getCommitOrder();
|
|
899
907
|
const commitOrderReversed = [...commitOrder].reverse();
|
|
@@ -925,7 +933,7 @@ export class UnitOfWork {
|
|
|
925
933
|
}
|
|
926
934
|
// take snapshots of all persisted collections
|
|
927
935
|
const visited = new Set();
|
|
928
|
-
for (const changeSet of this
|
|
936
|
+
for (const changeSet of this.#changeSets.values()) {
|
|
929
937
|
this.takeCollectionSnapshots(changeSet.entity, visited);
|
|
930
938
|
}
|
|
931
939
|
}
|
|
@@ -936,13 +944,13 @@ export class UnitOfWork {
|
|
|
936
944
|
const props = changeSets[0].meta.root.relations.filter(prop => {
|
|
937
945
|
return ((prop.kind === ReferenceKind.ONE_TO_ONE && prop.owner) ||
|
|
938
946
|
prop.kind === ReferenceKind.MANY_TO_ONE ||
|
|
939
|
-
(prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this
|
|
947
|
+
(prop.kind === ReferenceKind.MANY_TO_MANY && prop.owner && !this.#platform.usesPivotTable()));
|
|
940
948
|
});
|
|
941
949
|
for (const changeSet of changeSets) {
|
|
942
950
|
this.findExtraUpdates(changeSet, props);
|
|
943
951
|
await this.runHooks(EventType.beforeCreate, changeSet, true);
|
|
944
952
|
}
|
|
945
|
-
await this
|
|
953
|
+
await this.#changeSetPersister.executeInserts(changeSets, { ctx });
|
|
946
954
|
for (const changeSet of changeSets) {
|
|
947
955
|
this.register(changeSet.entity, changeSet.payload, { refresh: true });
|
|
948
956
|
await this.runHooks(EventType.afterCreate, changeSet);
|
|
@@ -956,7 +964,7 @@ export class UnitOfWork {
|
|
|
956
964
|
}
|
|
957
965
|
if (Utils.isCollection(ref)) {
|
|
958
966
|
ref.getItems(false).some(item => {
|
|
959
|
-
const cs = this
|
|
967
|
+
const cs = this.#changeSets.get(Reference.unwrapReference(item));
|
|
960
968
|
const isScheduledForInsert = cs?.type === ChangeSetType.CREATE && !cs.persisted;
|
|
961
969
|
if (isScheduledForInsert) {
|
|
962
970
|
this.scheduleExtraUpdate(changeSet, [prop]);
|
|
@@ -973,7 +981,7 @@ export class UnitOfWork {
|
|
|
973
981
|
}
|
|
974
982
|
// For TPT entities, check if the ROOT table's changeset has been persisted
|
|
975
983
|
// (since the FK is to the root table, not the concrete entity's table)
|
|
976
|
-
let cs = this
|
|
984
|
+
let cs = this.#changeSets.get(refEntity);
|
|
977
985
|
if (cs?.tptChangeSets?.length) {
|
|
978
986
|
// Root table changeset is the last one (ordered immediate parent → root)
|
|
979
987
|
cs = cs.tptChangeSets[cs.tptChangeSets.length - 1];
|
|
@@ -1005,10 +1013,10 @@ export class UnitOfWork {
|
|
|
1005
1013
|
for (const changeSet of changeSets) {
|
|
1006
1014
|
await this.runHooks(EventType.beforeUpdate, changeSet, true);
|
|
1007
1015
|
}
|
|
1008
|
-
await this
|
|
1016
|
+
await this.#changeSetPersister.executeUpdates(changeSets, batched, { ctx });
|
|
1009
1017
|
for (const changeSet of changeSets) {
|
|
1010
1018
|
const wrapped = helper(changeSet.entity);
|
|
1011
|
-
wrapped.__originalEntityData = this
|
|
1019
|
+
wrapped.__originalEntityData = this.#comparator.prepareEntity(changeSet.entity);
|
|
1012
1020
|
if (!wrapped.__initialized) {
|
|
1013
1021
|
for (const prop of changeSet.meta.relations) {
|
|
1014
1022
|
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) &&
|
|
@@ -1028,7 +1036,7 @@ export class UnitOfWork {
|
|
|
1028
1036
|
for (const changeSet of changeSets) {
|
|
1029
1037
|
await this.runHooks(EventType.beforeDelete, changeSet, true);
|
|
1030
1038
|
}
|
|
1031
|
-
await this
|
|
1039
|
+
await this.#changeSetPersister.executeDeletes(changeSets, { ctx });
|
|
1032
1040
|
for (const changeSet of changeSets) {
|
|
1033
1041
|
this.unsetIdentity(changeSet.entity);
|
|
1034
1042
|
await this.runHooks(EventType.afterDelete, changeSet);
|
|
@@ -1036,7 +1044,7 @@ export class UnitOfWork {
|
|
|
1036
1044
|
}
|
|
1037
1045
|
async commitExtraUpdates(type, ctx) {
|
|
1038
1046
|
const extraUpdates = [];
|
|
1039
|
-
for (const extraUpdate of this
|
|
1047
|
+
for (const extraUpdate of this.#extraUpdates) {
|
|
1040
1048
|
if (extraUpdate[4] !== type) {
|
|
1041
1049
|
continue;
|
|
1042
1050
|
}
|
|
@@ -1046,7 +1054,7 @@ export class UnitOfWork {
|
|
|
1046
1054
|
else {
|
|
1047
1055
|
extraUpdate[0][extraUpdate[1]] = extraUpdate[2];
|
|
1048
1056
|
}
|
|
1049
|
-
const changeSet = this
|
|
1057
|
+
const changeSet = this.#changeSetComputer.computeChangeSet(extraUpdate[0]);
|
|
1050
1058
|
if (changeSet) {
|
|
1051
1059
|
extraUpdates.push([changeSet, extraUpdate[3]]);
|
|
1052
1060
|
}
|
|
@@ -1061,21 +1069,21 @@ export class UnitOfWork {
|
|
|
1061
1069
|
}
|
|
1062
1070
|
async commitCollectionUpdates(ctx) {
|
|
1063
1071
|
this.filterCollectionUpdates();
|
|
1064
|
-
const loggerContext = Utils.merge({ id: this
|
|
1065
|
-
await this
|
|
1072
|
+
const loggerContext = Utils.merge({ id: this.#em._id }, this.#em.getLoggerContext({ disableContextResolution: true }));
|
|
1073
|
+
await this.#em.getDriver().syncCollections(this.#collectionUpdates, {
|
|
1066
1074
|
ctx,
|
|
1067
|
-
schema: this
|
|
1075
|
+
schema: this.#em.schema,
|
|
1068
1076
|
loggerContext,
|
|
1069
1077
|
});
|
|
1070
|
-
for (const coll of this
|
|
1078
|
+
for (const coll of this.#collectionUpdates) {
|
|
1071
1079
|
coll.takeSnapshot();
|
|
1072
1080
|
}
|
|
1073
1081
|
}
|
|
1074
1082
|
filterCollectionUpdates() {
|
|
1075
|
-
for (const coll of this
|
|
1083
|
+
for (const coll of this.#collectionUpdates) {
|
|
1076
1084
|
let skip = true;
|
|
1077
1085
|
if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
|
|
1078
|
-
if (this
|
|
1086
|
+
if (this.#platform.usesPivotTable()) {
|
|
1079
1087
|
skip = false;
|
|
1080
1088
|
}
|
|
1081
1089
|
}
|
|
@@ -1086,7 +1094,7 @@ export class UnitOfWork {
|
|
|
1086
1094
|
skip = false;
|
|
1087
1095
|
}
|
|
1088
1096
|
if (skip) {
|
|
1089
|
-
this
|
|
1097
|
+
this.#collectionUpdates.delete(coll);
|
|
1090
1098
|
}
|
|
1091
1099
|
}
|
|
1092
1100
|
}
|
|
@@ -1115,7 +1123,7 @@ export class UnitOfWork {
|
|
|
1115
1123
|
group.set(groupKey, classGroup);
|
|
1116
1124
|
}
|
|
1117
1125
|
};
|
|
1118
|
-
for (const cs of this
|
|
1126
|
+
for (const cs of this.#changeSets.values()) {
|
|
1119
1127
|
addToGroup(cs);
|
|
1120
1128
|
for (const parentCs of cs.tptChangeSets ?? []) {
|
|
1121
1129
|
addToGroup(parentCs);
|
|
@@ -1126,7 +1134,7 @@ export class UnitOfWork {
|
|
|
1126
1134
|
getCommitOrder() {
|
|
1127
1135
|
const calc = new CommitOrderCalculator();
|
|
1128
1136
|
const set = new Set();
|
|
1129
|
-
this
|
|
1137
|
+
this.#changeSets.forEach(cs => {
|
|
1130
1138
|
if (cs.meta.inheritanceType === 'tpt') {
|
|
1131
1139
|
set.add(cs.meta);
|
|
1132
1140
|
for (const parentCs of cs.tptChangeSets ?? []) {
|
|
@@ -1154,14 +1162,14 @@ export class UnitOfWork {
|
|
|
1154
1162
|
calc.addDependency(meta.tptParent._id, meta._id, 1);
|
|
1155
1163
|
}
|
|
1156
1164
|
}
|
|
1157
|
-
return calc.sort().map(id => this
|
|
1165
|
+
return calc.sort().map(id => this.#metadata.getById(id));
|
|
1158
1166
|
}
|
|
1159
1167
|
resetTransaction(oldTx) {
|
|
1160
1168
|
if (oldTx) {
|
|
1161
|
-
this
|
|
1169
|
+
this.#em.setTransactionContext(oldTx);
|
|
1162
1170
|
}
|
|
1163
1171
|
else {
|
|
1164
|
-
this
|
|
1172
|
+
this.#em.resetTransactionContext();
|
|
1165
1173
|
}
|
|
1166
1174
|
}
|
|
1167
1175
|
/**
|