@mikro-orm/core 7.0.0-dev.6 → 7.0.0-dev.61
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 +85 -32
- package/EntityManager.js +281 -178
- package/MikroORM.d.ts +8 -8
- package/MikroORM.js +31 -74
- package/README.md +3 -2
- package/cache/FileCacheAdapter.d.ts +2 -1
- package/cache/FileCacheAdapter.js +5 -4
- package/connections/Connection.d.ts +11 -7
- package/connections/Connection.js +16 -13
- package/decorators/Embeddable.d.ts +2 -0
- package/decorators/Embedded.d.ts +5 -11
- package/decorators/Entity.d.ts +20 -3
- package/decorators/Indexed.d.ts +2 -2
- package/decorators/ManyToMany.d.ts +2 -0
- package/decorators/ManyToOne.d.ts +4 -0
- package/decorators/OneToOne.d.ts +4 -0
- package/decorators/Property.d.ts +53 -9
- package/decorators/Transactional.d.ts +3 -1
- package/decorators/Transactional.js +6 -3
- package/decorators/index.d.ts +1 -1
- package/drivers/DatabaseDriver.d.ts +11 -5
- package/drivers/DatabaseDriver.js +13 -4
- package/drivers/IDatabaseDriver.d.ts +29 -5
- package/entity/ArrayCollection.d.ts +6 -4
- package/entity/ArrayCollection.js +27 -12
- package/entity/BaseEntity.d.ts +0 -1
- package/entity/BaseEntity.js +0 -3
- package/entity/Collection.d.ts +3 -4
- package/entity/Collection.js +34 -17
- package/entity/EntityAssigner.d.ts +1 -1
- package/entity/EntityAssigner.js +9 -1
- package/entity/EntityFactory.d.ts +7 -0
- package/entity/EntityFactory.js +63 -40
- package/entity/EntityHelper.js +26 -9
- package/entity/EntityLoader.d.ts +5 -4
- package/entity/EntityLoader.js +69 -36
- package/entity/EntityRepository.d.ts +1 -1
- package/entity/EntityValidator.js +2 -2
- package/entity/Reference.d.ts +9 -7
- package/entity/Reference.js +32 -5
- package/entity/WrappedEntity.d.ts +0 -2
- package/entity/WrappedEntity.js +1 -5
- package/entity/defineEntity.d.ts +555 -0
- package/entity/defineEntity.js +529 -0
- package/entity/index.d.ts +2 -0
- package/entity/index.js +2 -0
- package/entity/utils.d.ts +7 -0
- package/entity/utils.js +15 -3
- package/enums.d.ts +18 -5
- package/enums.js +13 -0
- package/errors.d.ts +6 -1
- package/errors.js +14 -4
- package/events/EventSubscriber.d.ts +3 -1
- package/hydration/ObjectHydrator.d.ts +4 -4
- package/hydration/ObjectHydrator.js +35 -24
- package/index.d.ts +2 -1
- package/index.js +1 -1
- package/logging/DefaultLogger.d.ts +1 -1
- package/logging/SimpleLogger.d.ts +1 -1
- package/metadata/EntitySchema.d.ts +8 -4
- package/metadata/EntitySchema.js +41 -23
- package/metadata/MetadataDiscovery.d.ts +5 -7
- package/metadata/MetadataDiscovery.js +151 -159
- package/metadata/MetadataStorage.js +1 -1
- package/metadata/MetadataValidator.js +4 -3
- package/metadata/discover-entities.d.ts +5 -0
- package/metadata/discover-entities.js +39 -0
- package/naming-strategy/AbstractNamingStrategy.d.ts +5 -1
- package/naming-strategy/AbstractNamingStrategy.js +7 -1
- package/naming-strategy/NamingStrategy.d.ts +11 -1
- package/package.json +14 -8
- package/platforms/Platform.d.ts +5 -8
- package/platforms/Platform.js +4 -17
- package/serialization/EntitySerializer.d.ts +2 -0
- package/serialization/EntitySerializer.js +29 -11
- package/serialization/EntityTransformer.js +22 -12
- package/serialization/SerializationContext.js +14 -11
- package/types/BigIntType.d.ts +9 -6
- package/types/BigIntType.js +3 -0
- package/types/BlobType.d.ts +0 -1
- package/types/BlobType.js +0 -3
- package/types/BooleanType.d.ts +2 -1
- package/types/BooleanType.js +3 -0
- package/types/DecimalType.d.ts +6 -4
- package/types/DecimalType.js +1 -1
- package/types/DoubleType.js +1 -1
- package/types/JsonType.d.ts +1 -1
- package/types/JsonType.js +7 -2
- package/types/Type.d.ts +2 -1
- package/types/Type.js +1 -1
- package/types/Uint8ArrayType.d.ts +0 -1
- package/types/Uint8ArrayType.js +0 -3
- package/types/index.d.ts +1 -1
- package/typings.d.ts +95 -52
- package/typings.js +31 -31
- package/unit-of-work/ChangeSetComputer.js +8 -3
- package/unit-of-work/ChangeSetPersister.d.ts +4 -2
- package/unit-of-work/ChangeSetPersister.js +37 -16
- package/unit-of-work/UnitOfWork.d.ts +8 -1
- package/unit-of-work/UnitOfWork.js +110 -53
- package/utils/AbstractSchemaGenerator.js +3 -1
- package/utils/Configuration.d.ts +201 -184
- package/utils/Configuration.js +143 -151
- package/utils/ConfigurationLoader.d.ts +9 -22
- package/utils/ConfigurationLoader.js +53 -76
- package/utils/Cursor.d.ts +3 -3
- package/utils/Cursor.js +3 -0
- package/utils/DataloaderUtils.d.ts +15 -5
- package/utils/DataloaderUtils.js +53 -7
- package/utils/EntityComparator.d.ts +8 -4
- package/utils/EntityComparator.js +105 -58
- package/utils/QueryHelper.d.ts +9 -1
- package/utils/QueryHelper.js +66 -5
- package/utils/RawQueryFragment.d.ts +36 -4
- package/utils/RawQueryFragment.js +34 -13
- package/utils/TransactionManager.d.ts +65 -0
- package/utils/TransactionManager.js +223 -0
- package/utils/Utils.d.ts +16 -31
- package/utils/Utils.js +129 -107
- package/utils/index.d.ts +1 -0
- package/utils/index.js +1 -0
- package/utils/upsert-utils.d.ts +7 -2
- package/utils/upsert-utils.js +52 -1
|
@@ -12,16 +12,18 @@ export class ChangeSetPersister {
|
|
|
12
12
|
factory;
|
|
13
13
|
validator;
|
|
14
14
|
config;
|
|
15
|
+
em;
|
|
15
16
|
platform;
|
|
16
17
|
comparator;
|
|
17
18
|
usesReturningStatement;
|
|
18
|
-
constructor(driver, metadata, hydrator, factory, validator, config) {
|
|
19
|
+
constructor(driver, metadata, hydrator, factory, validator, config, em) {
|
|
19
20
|
this.driver = driver;
|
|
20
21
|
this.metadata = metadata;
|
|
21
22
|
this.hydrator = hydrator;
|
|
22
23
|
this.factory = factory;
|
|
23
24
|
this.validator = validator;
|
|
24
25
|
this.config = config;
|
|
26
|
+
this.em = em;
|
|
25
27
|
this.platform = this.driver.getPlatform();
|
|
26
28
|
this.comparator = this.config.getComparator(this.metadata);
|
|
27
29
|
this.usesReturningStatement = this.platform.usesReturningStatement() || this.platform.usesOutputStatement();
|
|
@@ -62,7 +64,7 @@ export class ChangeSetPersister {
|
|
|
62
64
|
for (let i = 0; i < changeSets.length; i += size) {
|
|
63
65
|
const chunk = changeSets.slice(i, i + size);
|
|
64
66
|
const pks = chunk.map(cs => cs.getPrimaryKey());
|
|
65
|
-
options = this.
|
|
67
|
+
options = this.prepareOptions(meta, options);
|
|
66
68
|
await this.driver.nativeDelete(meta.root.className, { [pk]: { $in: pks } }, options);
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -90,7 +92,7 @@ export class ChangeSetPersister {
|
|
|
90
92
|
}
|
|
91
93
|
async persistNewEntity(meta, changeSet, options) {
|
|
92
94
|
const wrapped = helper(changeSet.entity);
|
|
93
|
-
options = this.
|
|
95
|
+
options = this.prepareOptions(meta, options, {
|
|
94
96
|
convertCustomTypes: false,
|
|
95
97
|
});
|
|
96
98
|
const res = await this.driver.nativeInsertMany(meta.className, [changeSet.payload], options);
|
|
@@ -116,15 +118,17 @@ export class ChangeSetPersister {
|
|
|
116
118
|
}
|
|
117
119
|
}
|
|
118
120
|
}
|
|
119
|
-
|
|
121
|
+
prepareOptions(meta, options, additionalOptions) {
|
|
122
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
120
123
|
return {
|
|
121
124
|
...options,
|
|
122
125
|
...additionalOptions,
|
|
123
126
|
schema: options?.schema ?? meta.schema,
|
|
127
|
+
loggerContext,
|
|
124
128
|
};
|
|
125
129
|
}
|
|
126
130
|
async persistNewEntitiesBatch(meta, changeSets, options) {
|
|
127
|
-
options = this.
|
|
131
|
+
options = this.prepareOptions(meta, options, {
|
|
128
132
|
convertCustomTypes: false,
|
|
129
133
|
processCollections: false,
|
|
130
134
|
});
|
|
@@ -175,7 +179,7 @@ export class ChangeSetPersister {
|
|
|
175
179
|
}
|
|
176
180
|
async persistManagedEntitiesBatch(meta, changeSets, options) {
|
|
177
181
|
await this.checkOptimisticLocks(meta, changeSets, options);
|
|
178
|
-
options = this.
|
|
182
|
+
options = this.prepareOptions(meta, options, {
|
|
179
183
|
convertCustomTypes: false,
|
|
180
184
|
processCollections: false,
|
|
181
185
|
});
|
|
@@ -210,7 +214,9 @@ export class ChangeSetPersister {
|
|
|
210
214
|
// of using the raw value from db, we convert it back to the db value explicitly
|
|
211
215
|
value = prop.customType ? prop.customType.convertToDatabaseValue(insertId, this.platform, { mode: 'serialization' }) : value;
|
|
212
216
|
changeSet.payload[wrapped.__meta.primaryKeys[0]] = value;
|
|
213
|
-
wrapped.__identifier
|
|
217
|
+
if (wrapped.__identifier && !Array.isArray(wrapped.__identifier)) {
|
|
218
|
+
wrapped.__identifier.setValue(value);
|
|
219
|
+
}
|
|
214
220
|
}
|
|
215
221
|
/**
|
|
216
222
|
* Sets populate flag to new entities so they are serialized like if they were loaded from the db
|
|
@@ -233,7 +239,7 @@ export class ChangeSetPersister {
|
|
|
233
239
|
}
|
|
234
240
|
async updateEntity(meta, changeSet, options) {
|
|
235
241
|
const cond = changeSet.getPrimaryKey(true);
|
|
236
|
-
options = this.
|
|
242
|
+
options = this.prepareOptions(meta, options, {
|
|
237
243
|
convertCustomTypes: false,
|
|
238
244
|
});
|
|
239
245
|
if (meta.concurrencyCheckKeys.size === 0 && (!meta.versionProperty || changeSet.entity[meta.versionProperty] == null)) {
|
|
@@ -260,7 +266,7 @@ export class ChangeSetPersister {
|
|
|
260
266
|
return cond;
|
|
261
267
|
});
|
|
262
268
|
const primaryKeys = meta.primaryKeys.concat(...meta.concurrencyCheckKeys);
|
|
263
|
-
options = this.
|
|
269
|
+
options = this.prepareOptions(meta, options, {
|
|
264
270
|
fields: primaryKeys,
|
|
265
271
|
});
|
|
266
272
|
const res = await this.driver.find(meta.root.className, { $or }, options);
|
|
@@ -284,11 +290,22 @@ export class ChangeSetPersister {
|
|
|
284
290
|
async reloadVersionValues(meta, changeSets, options) {
|
|
285
291
|
const reloadProps = meta.versionProperty && !this.usesReturningStatement ? [meta.properties[meta.versionProperty]] : [];
|
|
286
292
|
if (changeSets[0].type === ChangeSetType.CREATE) {
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
.
|
|
293
|
+
for (const prop of meta.props) {
|
|
294
|
+
if (prop.persist === false) {
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
if (isRaw(changeSets[0].entity[prop.name])) {
|
|
298
|
+
reloadProps.push(prop);
|
|
299
|
+
continue;
|
|
300
|
+
}
|
|
301
|
+
// do not reload things that already had a runtime value
|
|
302
|
+
if (changeSets[0].entity[prop.name] != null || prop.defaultRaw === 'null') {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
if (prop.autoincrement || prop.generated || prop.defaultRaw) {
|
|
306
|
+
reloadProps.push(prop);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
292
309
|
}
|
|
293
310
|
if (changeSets[0].type === ChangeSetType.UPDATE) {
|
|
294
311
|
const returning = new Set();
|
|
@@ -319,12 +336,12 @@ export class ChangeSetPersister {
|
|
|
319
336
|
}
|
|
320
337
|
return val;
|
|
321
338
|
});
|
|
322
|
-
options = this.
|
|
339
|
+
options = this.prepareOptions(meta, options, {
|
|
323
340
|
fields: Utils.unique(reloadProps.map(prop => prop.name)),
|
|
324
341
|
});
|
|
325
342
|
const data = await this.driver.find(meta.className, { [pk]: { $in: pks } }, options);
|
|
326
343
|
const map = new Map();
|
|
327
|
-
data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta,
|
|
344
|
+
data.forEach(item => map.set(Utils.getCompositeKeyHash(item, meta, false, this.platform, true), item));
|
|
328
345
|
for (const changeSet of changeSets) {
|
|
329
346
|
const data = map.get(helper(changeSet.entity).getSerializedPrimaryKey());
|
|
330
347
|
this.hydrator.hydrate(changeSet.entity, meta, data, this.factory, 'full', false, true);
|
|
@@ -338,6 +355,10 @@ export class ChangeSetPersister {
|
|
|
338
355
|
changeSet.payload[prop.name] = value.getValue();
|
|
339
356
|
return;
|
|
340
357
|
}
|
|
358
|
+
if (Array.isArray(value) && value.every(item => item instanceof EntityIdentifier)) {
|
|
359
|
+
changeSet.payload[prop.name] = value.map(item => item.getValue());
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
341
362
|
if (prop.kind === ReferenceKind.MANY_TO_MANY && Array.isArray(value)) {
|
|
342
363
|
changeSet.payload[prop.name] = value.map(val => val instanceof EntityIdentifier ? val.getValue() : val);
|
|
343
364
|
return;
|
|
@@ -28,6 +28,12 @@ export declare class UnitOfWork {
|
|
|
28
28
|
private working;
|
|
29
29
|
constructor(em: EntityManager);
|
|
30
30
|
merge<T extends object>(entity: T, visited?: Set<AnyEntity>): void;
|
|
31
|
+
/**
|
|
32
|
+
* Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
|
|
33
|
+
* we need to normalize the shape, so relation values are only raw FKs. This method handles that.
|
|
34
|
+
* @internal
|
|
35
|
+
*/
|
|
36
|
+
normalizeEntityData<T extends object>(meta: EntityMetadata<T>, data: EntityData<T>): void;
|
|
31
37
|
/**
|
|
32
38
|
* @internal
|
|
33
39
|
*/
|
|
@@ -39,7 +45,7 @@ export declare class UnitOfWork {
|
|
|
39
45
|
/**
|
|
40
46
|
* 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`.
|
|
41
47
|
*/
|
|
42
|
-
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string): T | undefined;
|
|
48
|
+
getById<T extends object>(entityName: string, id: Primary<T> | Primary<T>[], schema?: string, convertCustomTypes?: boolean): T | undefined;
|
|
43
49
|
tryGetById<T extends object>(entityName: string, where: FilterQuery<T>, schema?: string, strict?: boolean): T | null;
|
|
44
50
|
/**
|
|
45
51
|
* Returns map of all managed entities.
|
|
@@ -103,6 +109,7 @@ export declare class UnitOfWork {
|
|
|
103
109
|
private commitDeleteChangeSets;
|
|
104
110
|
private commitExtraUpdates;
|
|
105
111
|
private commitCollectionUpdates;
|
|
112
|
+
private filterCollectionUpdates;
|
|
106
113
|
/**
|
|
107
114
|
* Orders change sets so FK constrains are maintained, ensures stable order (needed for node < 11)
|
|
108
115
|
*/
|
|
@@ -43,7 +43,7 @@ export class UnitOfWork {
|
|
|
43
43
|
this.eventManager = this.em.getEventManager();
|
|
44
44
|
this.comparator = this.em.getComparator();
|
|
45
45
|
this.changeSetComputer = new ChangeSetComputer(this.em.getValidator(), this.collectionUpdates, this.metadata, this.platform, this.em.config, this.em);
|
|
46
|
-
this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config);
|
|
46
|
+
this.changeSetPersister = new ChangeSetPersister(this.em.getDriver(), this.metadata, this.em.config.getHydrator(this.metadata), this.em.getEntityFactory(), this.em.getValidator(), this.em.config, this.em);
|
|
47
47
|
}
|
|
48
48
|
merge(entity, visited) {
|
|
49
49
|
const wrapped = helper(entity);
|
|
@@ -61,10 +61,43 @@ export class UnitOfWork {
|
|
|
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
63
|
wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
|
|
64
|
-
wrapped.__touched = false;
|
|
65
64
|
}
|
|
66
65
|
this.cascade(entity, Cascade.MERGE, visited ?? new Set());
|
|
67
66
|
}
|
|
67
|
+
/**
|
|
68
|
+
* Entity data can wary in its shape, e.g. we might get a deep relation graph with joined strategy, but for diffing,
|
|
69
|
+
* we need to normalize the shape, so relation values are only raw FKs. This method handles that.
|
|
70
|
+
* @internal
|
|
71
|
+
*/
|
|
72
|
+
normalizeEntityData(meta, data) {
|
|
73
|
+
const forceUndefined = this.em.config.get('forceUndefined');
|
|
74
|
+
for (const key of Utils.keys(data)) {
|
|
75
|
+
const prop = meta.properties[key];
|
|
76
|
+
if (!prop) {
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
80
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
81
|
+
}
|
|
82
|
+
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
83
|
+
for (const p of prop.targetMeta.props) {
|
|
84
|
+
/* v8 ignore next */
|
|
85
|
+
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
86
|
+
data[prefix + p.name] = data[prop.name][p.name];
|
|
87
|
+
}
|
|
88
|
+
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta, true);
|
|
89
|
+
}
|
|
90
|
+
if (prop.hydrate === false && prop.customType?.ensureComparable(meta, prop)) {
|
|
91
|
+
const converted = prop.customType.convertToJSValue(data[key], this.platform, { key, mode: 'hydration', force: true });
|
|
92
|
+
data[key] = prop.customType.convertToDatabaseValue(converted, this.platform, { key, mode: 'hydration' });
|
|
93
|
+
}
|
|
94
|
+
if (forceUndefined) {
|
|
95
|
+
if (data[key] === null) {
|
|
96
|
+
data[key] = undefined;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
68
101
|
/**
|
|
69
102
|
* @internal
|
|
70
103
|
*/
|
|
@@ -82,31 +115,14 @@ export class UnitOfWork {
|
|
|
82
115
|
wrapped.__em ??= this.em;
|
|
83
116
|
wrapped.__managed = true;
|
|
84
117
|
if (data && (options?.refresh || !wrapped.__originalEntityData)) {
|
|
118
|
+
this.normalizeEntityData(wrapped.__meta, data);
|
|
85
119
|
for (const key of Utils.keys(data)) {
|
|
86
120
|
const prop = wrapped.__meta.properties[key];
|
|
87
|
-
if (
|
|
88
|
-
|
|
89
|
-
}
|
|
90
|
-
wrapped.__loadedProperties.add(key);
|
|
91
|
-
if ([ReferenceKind.MANY_TO_ONE, ReferenceKind.ONE_TO_ONE].includes(prop.kind) && Utils.isPlainObject(data[prop.name])) {
|
|
92
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
|
|
93
|
-
}
|
|
94
|
-
else if (prop.kind === ReferenceKind.EMBEDDED && !prop.object && Utils.isPlainObject(data[prop.name])) {
|
|
95
|
-
for (const p of prop.targetMeta.props) {
|
|
96
|
-
/* v8 ignore next */
|
|
97
|
-
const prefix = prop.prefix === false ? '' : prop.prefix === true ? prop.name + '_' : prop.prefix;
|
|
98
|
-
data[prefix + p.name] = data[prop.name][p.name];
|
|
99
|
-
}
|
|
100
|
-
data[prop.name] = Utils.getPrimaryKeyValues(data[prop.name], prop.targetMeta.primaryKeys, true);
|
|
101
|
-
}
|
|
102
|
-
if (forceUndefined) {
|
|
103
|
-
if (data[key] === null) {
|
|
104
|
-
data[key] = undefined;
|
|
105
|
-
}
|
|
121
|
+
if (prop) {
|
|
122
|
+
wrapped.__loadedProperties.add(key);
|
|
106
123
|
}
|
|
107
124
|
}
|
|
108
125
|
wrapped.__originalEntityData = data;
|
|
109
|
-
wrapped.__touched = false;
|
|
110
126
|
}
|
|
111
127
|
return entity;
|
|
112
128
|
}
|
|
@@ -125,7 +141,7 @@ export class UnitOfWork {
|
|
|
125
141
|
/**
|
|
126
142
|
* 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`.
|
|
127
143
|
*/
|
|
128
|
-
getById(entityName, id, schema) {
|
|
144
|
+
getById(entityName, id, schema, convertCustomTypes) {
|
|
129
145
|
if (id == null || (Array.isArray(id) && id.length === 0)) {
|
|
130
146
|
return undefined;
|
|
131
147
|
}
|
|
@@ -135,7 +151,16 @@ export class UnitOfWork {
|
|
|
135
151
|
hash = '' + id;
|
|
136
152
|
}
|
|
137
153
|
else {
|
|
138
|
-
|
|
154
|
+
let keys = Array.isArray(id) ? Utils.flatten(id) : [id];
|
|
155
|
+
keys = meta.getPrimaryProps(true).map((p, i) => {
|
|
156
|
+
if (!convertCustomTypes && p.customType) {
|
|
157
|
+
return p.customType.convertToDatabaseValue(keys[i], this.platform, {
|
|
158
|
+
key: p.name,
|
|
159
|
+
mode: 'hydration',
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
return keys[i];
|
|
163
|
+
});
|
|
139
164
|
hash = Utils.getPrimaryKeyHash(keys);
|
|
140
165
|
}
|
|
141
166
|
schema ??= meta.schema ?? this.em.config.getSchema();
|
|
@@ -185,10 +210,8 @@ export class UnitOfWork {
|
|
|
185
210
|
if (this.queuedActions.has(meta.className) || this.queuedActions.has(meta.root.className)) {
|
|
186
211
|
return true;
|
|
187
212
|
}
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
return true;
|
|
191
|
-
}
|
|
213
|
+
if (meta.discriminatorMap && Object.values(meta.discriminatorMap).some(v => this.queuedActions.has(v))) {
|
|
214
|
+
return true;
|
|
192
215
|
}
|
|
193
216
|
return false;
|
|
194
217
|
}
|
|
@@ -209,7 +232,6 @@ export class UnitOfWork {
|
|
|
209
232
|
this.changeSets.set(entity, cs);
|
|
210
233
|
this.persistStack.delete(entity);
|
|
211
234
|
wrapped.__originalEntityData = this.comparator.prepareEntity(entity);
|
|
212
|
-
wrapped.__touched = false;
|
|
213
235
|
}
|
|
214
236
|
recomputeSingleChangeSet(entity) {
|
|
215
237
|
const changeSet = this.changeSets.get(entity);
|
|
@@ -220,7 +242,6 @@ export class UnitOfWork {
|
|
|
220
242
|
if (cs && !this.checkUniqueProps(cs)) {
|
|
221
243
|
Object.assign(changeSet.payload, cs.payload);
|
|
222
244
|
helper(entity).__originalEntityData = this.comparator.prepareEntity(entity);
|
|
223
|
-
helper(entity).__touched = false;
|
|
224
245
|
}
|
|
225
246
|
}
|
|
226
247
|
persist(entity, visited, options = {}) {
|
|
@@ -303,6 +324,7 @@ export class UnitOfWork {
|
|
|
303
324
|
cs.entity.__helper.__processing = true;
|
|
304
325
|
}
|
|
305
326
|
await this.eventManager.dispatchEvent(EventType.onFlush, { em: this.em, uow: this });
|
|
327
|
+
this.filterCollectionUpdates();
|
|
306
328
|
// nothing to do, do not start transaction
|
|
307
329
|
if (this.changeSets.size === 0 && this.collectionUpdates.size === 0 && this.extraUpdates.size === 0) {
|
|
308
330
|
return void (await this.eventManager.dispatchEvent(EventType.afterFlush, { em: this.em, uow: this }));
|
|
@@ -311,9 +333,11 @@ export class UnitOfWork {
|
|
|
311
333
|
const platform = this.em.getPlatform();
|
|
312
334
|
const runInTransaction = !this.em.isInTransaction() && platform.supportsTransactions() && this.em.config.get('implicitTransactions');
|
|
313
335
|
if (runInTransaction) {
|
|
336
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
314
337
|
await this.em.getConnection('write').transactional(trx => this.persistToDatabase(groups, trx), {
|
|
315
338
|
ctx: oldTx,
|
|
316
339
|
eventBroadcaster: new TransactionEventBroadcaster(this.em),
|
|
340
|
+
loggerContext,
|
|
317
341
|
});
|
|
318
342
|
}
|
|
319
343
|
else {
|
|
@@ -369,7 +393,6 @@ export class UnitOfWork {
|
|
|
369
393
|
}
|
|
370
394
|
delete wrapped.__identifier;
|
|
371
395
|
delete wrapped.__originalEntityData;
|
|
372
|
-
wrapped.__touched = false;
|
|
373
396
|
wrapped.__managed = false;
|
|
374
397
|
}
|
|
375
398
|
computeChangeSets() {
|
|
@@ -379,14 +402,14 @@ export class UnitOfWork {
|
|
|
379
402
|
this.cascade(entity, Cascade.REMOVE, visited);
|
|
380
403
|
}
|
|
381
404
|
visited.clear();
|
|
382
|
-
for (const entity of this.persistStack) {
|
|
383
|
-
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
384
|
-
}
|
|
385
405
|
for (const entity of this.identityMap) {
|
|
386
406
|
if (!this.removeStack.has(entity) && !this.persistStack.has(entity) && !this.orphanRemoveStack.has(entity)) {
|
|
387
407
|
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
388
408
|
}
|
|
389
409
|
}
|
|
410
|
+
for (const entity of this.persistStack) {
|
|
411
|
+
this.cascade(entity, Cascade.PERSIST, visited, { checkRemoveStack: true });
|
|
412
|
+
}
|
|
390
413
|
visited.clear();
|
|
391
414
|
for (const entity of this.persistStack) {
|
|
392
415
|
this.findNewEntities(entity, visited);
|
|
@@ -542,13 +565,22 @@ export class UnitOfWork {
|
|
|
542
565
|
if (!wrapped || wrapped.__identifier || wrapped.hasPrimaryKey()) {
|
|
543
566
|
return;
|
|
544
567
|
}
|
|
545
|
-
const
|
|
546
|
-
|
|
547
|
-
|
|
568
|
+
const pks = wrapped.__meta.getPrimaryProps();
|
|
569
|
+
const idents = [];
|
|
570
|
+
for (const pk of pks) {
|
|
571
|
+
if (pk.kind === ReferenceKind.SCALAR) {
|
|
572
|
+
idents.push(new EntityIdentifier(entity[pk.name]));
|
|
573
|
+
}
|
|
574
|
+
else if (entity[pk.name]) {
|
|
575
|
+
this.initIdentifier(entity[pk.name]);
|
|
576
|
+
idents.push(helper(entity[pk.name])?.__identifier);
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
if (pks.length === 1) {
|
|
580
|
+
wrapped.__identifier = idents[0];
|
|
548
581
|
}
|
|
549
|
-
else
|
|
550
|
-
|
|
551
|
-
wrapped.__identifier = helper(entity[pk.name])?.__identifier;
|
|
582
|
+
else {
|
|
583
|
+
wrapped.__identifier = idents;
|
|
552
584
|
}
|
|
553
585
|
}
|
|
554
586
|
processReference(parent, prop, kind, visited, processed, idx) {
|
|
@@ -600,8 +632,15 @@ export class UnitOfWork {
|
|
|
600
632
|
const diff = this.comparator.diffEntities(changeSet.name, copy, current);
|
|
601
633
|
Object.assign(changeSet.payload, diff);
|
|
602
634
|
const wrapped = helper(changeSet.entity);
|
|
603
|
-
if (wrapped.__identifier
|
|
604
|
-
|
|
635
|
+
if (wrapped.__identifier) {
|
|
636
|
+
const idents = Utils.asArray(wrapped.__identifier);
|
|
637
|
+
let i = 0;
|
|
638
|
+
for (const pk of wrapped.__meta.primaryKeys) {
|
|
639
|
+
if (diff[pk]) {
|
|
640
|
+
idents[i].setValue(diff[pk]);
|
|
641
|
+
}
|
|
642
|
+
i++;
|
|
643
|
+
}
|
|
605
644
|
}
|
|
606
645
|
}
|
|
607
646
|
postCommitCleanup() {
|
|
@@ -825,9 +864,16 @@ export class UnitOfWork {
|
|
|
825
864
|
}
|
|
826
865
|
await this.changeSetPersister.executeUpdates(changeSets, batched, { ctx });
|
|
827
866
|
for (const changeSet of changeSets) {
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
867
|
+
const wrapped = helper(changeSet.entity);
|
|
868
|
+
wrapped.__originalEntityData = this.comparator.prepareEntity(changeSet.entity);
|
|
869
|
+
if (!wrapped.__initialized) {
|
|
870
|
+
for (const prop of changeSet.meta.relations) {
|
|
871
|
+
if ([ReferenceKind.MANY_TO_MANY, ReferenceKind.ONE_TO_MANY].includes(prop.kind) && changeSet.entity[prop.name] == null) {
|
|
872
|
+
changeSet.entity[prop.name] = Collection.create(changeSet.entity, prop.name, undefined, wrapped.isInitialized());
|
|
873
|
+
}
|
|
874
|
+
}
|
|
875
|
+
wrapped.__initialized = true;
|
|
876
|
+
}
|
|
831
877
|
await this.runHooks(EventType.afterUpdate, changeSet);
|
|
832
878
|
}
|
|
833
879
|
}
|
|
@@ -870,23 +916,34 @@ export class UnitOfWork {
|
|
|
870
916
|
}
|
|
871
917
|
}
|
|
872
918
|
async commitCollectionUpdates(ctx) {
|
|
873
|
-
|
|
919
|
+
this.filterCollectionUpdates();
|
|
920
|
+
const loggerContext = Utils.merge({ id: this.em._id }, this.em.getLoggerContext({ disableContextResolution: true }));
|
|
921
|
+
await this.em.getDriver().syncCollections(this.collectionUpdates, {
|
|
922
|
+
ctx,
|
|
923
|
+
schema: this.em.schema,
|
|
924
|
+
loggerContext,
|
|
925
|
+
});
|
|
926
|
+
for (const coll of this.collectionUpdates) {
|
|
927
|
+
coll.takeSnapshot();
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
filterCollectionUpdates() {
|
|
874
931
|
for (const coll of this.collectionUpdates) {
|
|
932
|
+
let skip = true;
|
|
875
933
|
if (coll.property.owner || coll.getItems(false).filter(item => !item.__helper.__initialized).length > 0) {
|
|
876
934
|
if (this.platform.usesPivotTable()) {
|
|
877
|
-
|
|
935
|
+
skip = false;
|
|
878
936
|
}
|
|
879
937
|
}
|
|
880
938
|
else if (coll.property.kind === ReferenceKind.ONE_TO_MANY && coll.getSnapshot() === undefined) {
|
|
881
|
-
|
|
939
|
+
skip = false;
|
|
882
940
|
}
|
|
883
941
|
else if (coll.property.kind === ReferenceKind.MANY_TO_MANY && !coll.property.owner) {
|
|
884
|
-
|
|
942
|
+
skip = false;
|
|
943
|
+
}
|
|
944
|
+
if (skip) {
|
|
945
|
+
this.collectionUpdates.delete(coll);
|
|
885
946
|
}
|
|
886
|
-
}
|
|
887
|
-
await this.em.getDriver().syncCollections(collectionUpdates, { ctx, schema: this.em.schema });
|
|
888
|
-
for (const coll of this.collectionUpdates) {
|
|
889
|
-
coll.takeSnapshot();
|
|
890
947
|
}
|
|
891
948
|
}
|
|
892
949
|
/**
|
|
@@ -42,7 +42,9 @@ export class AbstractSchemaGenerator {
|
|
|
42
42
|
for (const meta of this.getOrderedMetadata(options?.schema).reverse()) {
|
|
43
43
|
await this.driver.nativeDelete(meta.className, {}, options);
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
if (options?.clearIdentityMap ?? true) {
|
|
46
|
+
this.clearIdentityMap();
|
|
47
|
+
}
|
|
46
48
|
}
|
|
47
49
|
clearIdentityMap() {
|
|
48
50
|
/* v8 ignore next 3 */
|