refactoring entity metadata stuff

This commit is contained in:
Umed Khudoiberdiev 2017-05-16 12:00:02 +05:00
parent 32505c6f47
commit 76924c63b8
10 changed files with 188 additions and 219 deletions

View File

@ -212,19 +212,19 @@ export class EntityMetadataBuilder {
entityMetadata.manyToManyRelations = entityMetadata.relations.filter(relation => relation.isManyToMany);
entityMetadata.ownerOneToOneRelations = entityMetadata.relations.filter(relation => relation.isOneToOneOwner);
entityMetadata.ownerManyToManyRelations = entityMetadata.relations.filter(relation => relation.isManyToManyOwner);
entityMetadata.treeParentRelation = entityMetadata.relations.find(relation => relation.isTreeParent)!; // todo: fix ! later
entityMetadata.treeChildrenRelation = entityMetadata.relations.find(relation => relation.isTreeChildren)!; // todo: fix ! later
entityMetadata.treeParentRelation = entityMetadata.relations.find(relation => relation.isTreeParent);
entityMetadata.treeChildrenRelation = entityMetadata.relations.find(relation => relation.isTreeChildren);
entityMetadata.columns = entityMetadata.embeddeds.reduce((columns, embedded) => columns.concat(embedded.columnsFromTree), entityMetadata.ownColumns);
entityMetadata.primaryColumns = entityMetadata.columns.filter(column => column.isPrimary);
entityMetadata.hasMultiplePrimaryKeys = entityMetadata.primaryColumns.length > 1;
entityMetadata.generatedColumn = entityMetadata.columns.find(column => column.isGenerated)!; // todo: fix ! later
entityMetadata.createDateColumn = entityMetadata.columns.find(column => column.mode === "createDate")!; // todo: fix ! later
entityMetadata.updateDateColumn = entityMetadata.columns.find(column => column.mode === "updateDate")!; // todo: fix ! later
entityMetadata.versionColumn = entityMetadata.columns.find(column => column.mode === "version")!; // todo: fix ! later
entityMetadata.discriminatorColumn = entityMetadata.columns.find(column => column.mode === "discriminator")!; // todo: fix ! later
entityMetadata.treeLevelColumn = entityMetadata.columns.find(column => column.mode === "treeLevel")!; // todo: fix ! later
entityMetadata.parentIdColumns = entityMetadata.columns.filter(column => column.mode === "parentId")!; // todo: fix ! later
entityMetadata.objectIdColumn = entityMetadata.columns.find(column => column.mode === "objectId")!; // todo: fix ! later
entityMetadata.generatedColumn = entityMetadata.columns.find(column => column.isGenerated);
entityMetadata.createDateColumn = entityMetadata.columns.find(column => column.mode === "createDate");
entityMetadata.updateDateColumn = entityMetadata.columns.find(column => column.mode === "updateDate");
entityMetadata.versionColumn = entityMetadata.columns.find(column => column.mode === "version");
entityMetadata.discriminatorColumn = entityMetadata.columns.find(column => column.mode === "discriminator");
entityMetadata.treeLevelColumn = entityMetadata.columns.find(column => column.mode === "treeLevel");
entityMetadata.parentIdColumns = entityMetadata.columns.filter(column => column.mode === "parentId");
entityMetadata.objectIdColumn = entityMetadata.columns.find(column => column.mode === "objectId");
entityMetadata.foreignKeys.forEach(foreignKey => foreignKey.build(this.connection.driver.namingStrategy));
entityMetadata.indices.forEach(index => index.build(this.connection.driver.namingStrategy));
entityMetadata.propertiesMap = entityMetadata.createPropertiesMap();
@ -257,7 +257,7 @@ export class EntityMetadataBuilder {
entityMetadata.indices.push(
new IndexMetadata({
entityMetadata: entityMetadata,
columns: [entityMetadata.discriminatorColumn],
columns: [entityMetadata.discriminatorColumn!],
args: {
target: entityMetadata.target,
unique: false
@ -265,7 +265,7 @@ export class EntityMetadataBuilder {
}),
new IndexMetadata({
entityMetadata: entityMetadata,
columns: [...entityMetadata.primaryColumns, entityMetadata.discriminatorColumn],
columns: [...entityMetadata.primaryColumns, entityMetadata.discriminatorColumn!],
args: {
target: entityMetadata.target,
unique: false

View File

@ -10,7 +10,6 @@ import {RelationCountMetadata} from "./RelationCountMetadata";
import {TableType} from "./types/TableTypes";
import {OrderByCondition} from "../find-options/OrderByCondition";
import {OrmUtils} from "../util/OrmUtils";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
import {TableMetadataArgs} from "../metadata-args/TableMetadataArgs";
import {Connection} from "../connection/Connection";
@ -34,7 +33,7 @@ export class EntityMetadata {
closureJunctionTable: EntityMetadata;
/**
* If this is entity metadata for a junction closure table then its owner closure table metadata will be there.
* If this is entity metadata for a junction closure table then its owner closure table metadata will be set here.
*/
parentClosureEntityMetadata: EntityMetadata;
@ -43,68 +42,6 @@ export class EntityMetadata {
*/
parentEntityMetadata: EntityMetadata;
/**
* Specifies a default order by used for queries from this table when no explicit order by is specified.
*/
orderBy?: OrderByCondition;
/**
* Entity's column metadatas defined by user.
*/
ownColumns: ColumnMetadata[] = [];
/**
* Entity's relation metadatas.
*/
ownRelations: RelationMetadata[] = [];
/**
* Relations of the entity, including relations that are coming from the embeddeds of this entity.
*/
relations: RelationMetadata[] = [];
/**
* Columns of the entity, including columns that are coming from the embeddeds of this entity.
*/
columns: ColumnMetadata[] = [];
/**
* Entity's relation id metadatas.
*/
relationIds: RelationIdMetadata[] = [];
/**
* Entity's relation id metadatas.
*/
relationCounts: RelationCountMetadata[] = [];
/**
* Entity's index metadatas.
*/
indices: IndexMetadata[] = [];
/**
* Entity's foreign key metadatas.
*/
foreignKeys: ForeignKeyMetadata[] = [];
/**
* Entity's embedded metadatas.
*/
embeddeds: EmbeddedMetadata[] = [];
/**
* If this entity metadata's table using one of the inheritance patterns,
* then this will contain what pattern it uses.
*/
inheritanceType?: "single-table"|"class-table";
/**
* If this entity metadata is a child table of some table, it should have a discriminator value.
* Used to store a value in a discriminator column.
*/
discriminatorValue?: string;
/**
* Table type. Tables can be abstract, closure, junction, embedded, etc.
*/
@ -169,6 +106,68 @@ export class EntityMetadata {
*/
engine?: string;
/**
* Specifies a default order by used for queries from this table when no explicit order by is specified.
*/
orderBy?: OrderByCondition;
/**
* Entity's column metadatas defined by user.
*/
ownColumns: ColumnMetadata[] = [];
/**
* Entity's relation metadatas.
*/
ownRelations: RelationMetadata[] = [];
/**
* Relations of the entity, including relations that are coming from the embeddeds of this entity.
*/
relations: RelationMetadata[] = [];
/**
* Columns of the entity, including columns that are coming from the embeddeds of this entity.
*/
columns: ColumnMetadata[] = [];
/**
* Entity's relation id metadatas.
*/
relationIds: RelationIdMetadata[] = [];
/**
* Entity's relation id metadatas.
*/
relationCounts: RelationCountMetadata[] = [];
/**
* Entity's index metadatas.
*/
indices: IndexMetadata[] = [];
/**
* Entity's foreign key metadatas.
*/
foreignKeys: ForeignKeyMetadata[] = [];
/**
* Entity's embedded metadatas.
*/
embeddeds: EmbeddedMetadata[] = [];
/**
* If this entity metadata's table using one of the inheritance patterns,
* then this will contain what pattern it uses.
*/
inheritanceType?: "single-table"|"class-table";
/**
* If this entity metadata is a child table of some table, it should have a discriminator value.
* Used to store a value in a discriminator column.
*/
discriminatorValue?: string;
/**
* Checks if entity's table has multiple primary columns.
*/
@ -177,7 +176,7 @@ export class EntityMetadata {
/**
* Gets the column with generated flag.
*/
generatedColumn: ColumnMetadata;
generatedColumn?: ColumnMetadata;
/**
* Gets the primary columns.
@ -187,31 +186,31 @@ export class EntityMetadata {
/**
* Gets entity column which contains a create date value.
*/
createDateColumn: ColumnMetadata;
createDateColumn?: ColumnMetadata;
/**
* Gets entity column which contains an update date value.
*/
updateDateColumn: ColumnMetadata;
updateDateColumn?: ColumnMetadata;
/**
* Gets entity column which contains an entity version.
*/
versionColumn: ColumnMetadata;
versionColumn?: ColumnMetadata;
/**
* Gets the discriminator column used to store entity identificator in single-table inheritance tables.
*/
discriminatorColumn: ColumnMetadata;
discriminatorColumn?: ColumnMetadata;
treeLevelColumn: ColumnMetadata;
treeLevelColumn?: ColumnMetadata;
parentIdColumns: ColumnMetadata[];
parentIdColumns: ColumnMetadata[] = [];
/**
* Gets the object id column used with mongodb database.
*/
objectIdColumn: ColumnMetadata;
objectIdColumn?: ColumnMetadata;
/**
* Gets only one-to-one relations of the entity.
@ -251,12 +250,12 @@ export class EntityMetadata {
/**
* Tree parent relation. Used only in tree-tables.
*/
treeParentRelation: RelationMetadata;
treeParentRelation?: RelationMetadata;
/**
* Tree children relation. Used only in tree-tables.
*/
treeChildrenRelation: RelationMetadata;
treeChildrenRelation?: RelationMetadata;
/**
* Checks if there any non-nullable column exist in this entity.
@ -373,6 +372,63 @@ export class EntityMetadata {
return newObject;
}
/**
* Checks if given entity has an id.
*/
hasId(entity: ObjectLiteral): boolean {
if (!entity)
return false;
return this.primaryColumns.every(primaryColumn => { /// todo: this.metadata.parentEntityMetadata ?
const value = primaryColumn.getEntityValue(entity);
return value !== null && value !== undefined && value !== "";
});
}
/**
* Compares ids of the two entities.
* Returns true if they match, false otherwise.
*/
compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean {
if (firstId === undefined || firstId === null || secondId === undefined || secondId === null)
return false;
return OrmUtils.deepCompare(firstId, secondId);
}
/**
* Compares two different entity instances by their ids.
* Returns true if they match, false otherwise.
*/
compareEntities(firstEntity: ObjectLiteral, secondEntity: ObjectLiteral): boolean {
// if any entity ids are empty then they aren't equal
const isFirstEntityEmpty = this.isEntityMapEmpty(firstEntity);
const isSecondEntityEmpty = this.isEntityMapEmpty(secondEntity);
if (isFirstEntityEmpty || isSecondEntityEmpty)
return false;
const firstEntityIds = this.getEntityIdMap(firstEntity);
const secondEntityIds = this.getEntityIdMap(secondEntity);
return this.compareIds(firstEntityIds, secondEntityIds);
}
/**
* Finds relation with the given name.
*/
findRelationWithDbName(dbName: string): RelationMetadata|undefined {
return this.relationsWithJoinColumns.find(relation => {
return !!relation.joinColumns.find(column => column.databaseName === dbName);
});
}
/**
* Finds relation with the given property path.
*/
findRelationWithPropertyPath(propertyPath: string): RelationMetadata|undefined {
return this.relations.find(relation => relation.propertyPath === propertyPath);
}
/**
* Computes property name of the entity using given PropertyTypeInFunction.
*/
@ -460,97 +516,15 @@ export class EntityMetadata {
}
/**
* Same as `getEntityIdMap` but the key of the map will be the column names instead of the property names.
* Checks if given object contains ALL primary keys entity must have.
* Returns true if it contains all of them, false if at least one of them is not defined.
*/
getEntityIdColumnMap(entity: any): ObjectLiteral|undefined {
return this.getDatabaseEntityIdMap(entity);
// return this.transformIdMapToColumnNames(this.getEntityIdMap(entity));
}
/**
* Checks if relation with the given property path exist.
*
* todo: check usages later
*/
hasRelationWithPropertyPath(propertyPath: string): boolean {
return !!this.relations.find(relation => relation.propertyPath === propertyPath);
}
/**
* Finds relation with the given property name.
*/
findRelationWithPropertyName(propertyName: string): RelationMetadata {
const relation = this.relations.find(relation => relation.propertyName === propertyName);
if (!relation)
throw new Error(`Relation with property name ${propertyName} in ${this.name} entity was not found.`);
return relation;
}
/**
* Finds relation with the given property path.
*
* todo: check usages later
*/
findRelationWithPropertyPath(propertyPath: string): RelationMetadata {
const relation = this.relations.find(relation => relation.propertyPath === propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in ${this.name} entity was not found.`);
return relation;
}
/**
* Checks if relation with the given name exist.
*/
hasRelationWithDbName(dbName: string): boolean {
return !!this.relationsWithJoinColumns.find(relation => {
return !!relation.joinColumns.find(column => column.databaseName === dbName);
});
}
/**
* Finds relation with the given name.
*/
findRelationWithDbName(dbName: string): RelationMetadata {
const relation = this.relationsWithJoinColumns.find(relation => {
return !!relation.joinColumns.find(column => column.databaseName === dbName);
});
if (!relation)
throw new Error(`Relation with name ${dbName} in ${this.name} entity was not found.`);
return relation;
}
checkIfObjectContainsAllPrimaryKeys(object: ObjectLiteral) {
return this.primaryColumns.every(primaryColumn => {
return object.hasOwnProperty(primaryColumn.propertyName);
});
}
/**
* @stable
*/
compareEntities(firstEntity: any, secondEntity: any) {
// if any entity ids are empty then they aren't equal
const isFirstEntityEmpty = this.isEntityMapEmpty(firstEntity);
const isSecondEntityEmpty = this.isEntityMapEmpty(secondEntity);
if (isFirstEntityEmpty || isSecondEntityEmpty)
return false;
const firstEntityIds = this.getEntityIdMap(firstEntity);
const secondEntityIds = this.getEntityIdMap(secondEntity);
return this.compareIds(firstEntityIds, secondEntityIds);
}
compareIds(firstId: ObjectLiteral|undefined, secondId: ObjectLiteral|undefined): boolean {
if (firstId === undefined || firstId === null || secondId === undefined || secondId === null)
return false;
return OrmUtils.deepCompare(firstId, secondId);
}
/**
* Iterates throw entity and finds and extracts all values from relations in the entity.
* If relation value is an array its being flattened.
@ -568,21 +542,8 @@ export class EntityMetadata {
return relationsAndValues;
}
/**
* Checks if given entity has an id.
*/
hasId(entity: ObjectLiteral): boolean {
if (!entity)
return false;
return this.primaryColumns.every(primaryColumn => { /// todo: this.metadata.parentEntityMetadata ?
const value = primaryColumn.getEntityValue(entity);
return value !== null && value !== undefined && value !== "";
});
}
// ---------------------------------------------------------------------
// Public Builder Methods
// Public Methods
// ---------------------------------------------------------------------
registerColumn(column: ColumnMetadata) {
@ -600,20 +561,4 @@ export class EntityMetadata {
return map;
}
// buildOnRelationsChange() {
// this.relationsWithJoinColumns = this.relations.filter(relation => relation.isWithJoinColumn);
// this.hasNonNullableRelations = this.relationsWithJoinColumns.some(relation => !relation.isNullable || relation.isPrimary);
// }
// buildOnColumnsChange() {
// this.columns = this.embeddeds.reduce((columns, embedded) => columns.concat(embedded.columnsFromTree), this.ownColumns);
// this.primaryColumns = this.columns.filter(column => column.isPrimary);
// this.hasMultiplePrimaryKeys = this.primaryColumns.length > 1;
// this.propertiesMap = this.createPropertiesMap();
// }
// ---------------------------------------------------------------------
// Protected Methods
// ---------------------------------------------------------------------
}

View File

@ -372,8 +372,8 @@ export class Subject {
return false;
// filter out "relational columns" only in the case if there is a relation object in entity
if (this.metadata.hasRelationWithDbName(column.databaseName)) {
const relation = this.metadata.findRelationWithDbName(column.databaseName);
const relation = this.metadata.findRelationWithDbName(column.databaseName);
if (relation) {
const value = relation.getEntityValue(this.entity);
if (value !== null && value !== undefined)
return false;

View File

@ -606,7 +606,7 @@ export class SubjectOperationExecutor {
// todo: since closure tables do not support compose primary keys - throw an exception?
// todo: what if parent entity or parentEntityId is empty?!
const tableName = subject.metadata.closureJunctionTable.tableName;
const referencedColumn = subject.metadata.treeParentRelation.joinColumns[0].referencedColumn!; // todo: check if joinColumn works
const referencedColumn = subject.metadata.treeParentRelation!.joinColumns[0].referencedColumn!; // todo: check if joinColumn works
// todo: fix joinColumns[0] usage
let newEntityId = referencedColumn.getEntityValue(subject.entity);
@ -615,7 +615,7 @@ export class SubjectOperationExecutor {
// we should not handle object id here because closure tables are not supported by mongodb driver.
} // todo: implement other special column types too
const parentEntity = subject.metadata.treeParentRelation.getEntityValue(subject.entity);
const parentEntity = subject.metadata.treeParentRelation!.getEntityValue(subject.entity);
let parentEntityId: any = 0; // zero is important
if (parentEntity) {
parentEntityId = referencedColumn.getEntityValue(parentEntity);
@ -632,7 +632,7 @@ export class SubjectOperationExecutor {
if (!allSubject.hasEntity || !allSubject.metadata.isClosure || !allSubject.metadata.treeChildrenRelation)
return false;
const children = subject.metadata.treeChildrenRelation.getEntityValue(allSubject.entity);
const children = subject.metadata.treeChildrenRelation!.getEntityValue(allSubject.entity);
return children instanceof Array ? children.indexOf(subject.entity) !== -1 : false;
});
@ -848,7 +848,7 @@ export class SubjectOperationExecutor {
});
await this.queryRunner.delete(subject.metadata.tableName, childConditions);
} else {
await this.queryRunner.delete(subject.metadata.tableName, subject.metadata.getEntityIdColumnMap(subject.databaseEntity)!);
await this.queryRunner.delete(subject.metadata.tableName, subject.metadata.getDatabaseEntityIdMap(subject.databaseEntity)!);
}
}

View File

@ -119,7 +119,10 @@ export class JoinAttribute {
return undefined;
const relationOwnerSelection = this.queryExpressionMap.findAliasByName(this.parentAlias!);
return relationOwnerSelection.metadata.findRelationWithPropertyPath(this.relationPropertyPath!);
const relation = relationOwnerSelection.metadata.findRelationWithPropertyPath(this.relationPropertyPath!);
if (!relation)
throw new Error(`Relation with property path ${this.relationPropertyPath} in entity was not found.`);
return relation;
}
/**

View File

@ -1083,13 +1083,13 @@ export class QueryBuilder<Entity> {
const metadata = this.expressionMap.mainAlias!.metadata;
if (this.expressionMap.lockVersion instanceof Date) {
const actualVersion = result[metadata.updateDateColumn.propertyName];
const actualVersion = result[metadata.updateDateColumn!.propertyName]; // what if columns arent set?
this.expressionMap.lockVersion.setMilliseconds(0);
if (actualVersion.getTime() !== this.expressionMap.lockVersion.getTime())
throw new OptimisticLockVersionMismatchError(metadata.name, this.expressionMap.lockVersion, actualVersion);
} else {
const actualVersion = result[metadata.versionColumn.propertyName];
const actualVersion = result[metadata.versionColumn!.propertyName]; // what if columns arent set?
if (actualVersion !== this.expressionMap.lockVersion)
throw new OptimisticLockVersionMismatchError(metadata.name, this.expressionMap.lockVersion, actualVersion);
}

View File

@ -84,9 +84,12 @@ export class RelationCountAttribute {
if (!QueryBuilderUtils.isAliasProperty(this.relationName))
throw new Error(`Given value is a string representation of alias property`);
const [parentAlias, relationProperty] = this.relationName.split(".");
const [parentAlias, propertyPath] = this.relationName.split(".");
const relationOwnerSelection = this.expressionMap.findAliasByName(parentAlias);
return relationOwnerSelection.metadata.findRelationWithPropertyName(relationProperty);
const relation = relationOwnerSelection.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
return relation;
}
/**

View File

@ -87,7 +87,10 @@ export class RelationIdAttribute {
throw new Error(`Given value must be a string representation of alias property`);
const relationOwnerSelection = this.queryExpressionMap.findAliasByName(this.parentAlias!);
return relationOwnerSelection.metadata.findRelationWithPropertyPath(this.relationPropertyPath!);
const relation = relationOwnerSelection.metadata.findRelationWithPropertyPath(this.relationPropertyPath!);
if (!relation)
throw new Error(`Relation with property path ${this.relationPropertyPath} in entity was not found.`);
return relation;
}
/**

View File

@ -50,6 +50,8 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
async setRelation(relationProperty: string|((t: Entity) => string|any), entityId: any, relatedEntityId: any): Promise<void> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
// if (relation.isManyToMany || relation.isOneToMany || relation.isOneToOneNotOwner)
// throw new Error(`Only many-to-one and one-to-one with join column are supported for this operation. ${this.metadata.name}#${propertyName} relation type is ${relation.relationType}`);
if (relation.isManyToMany)
@ -99,6 +101,8 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
// todo: fix issues with joinColumns[0]
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
// if (relation.isManyToMany || relation.isOneToMany || relation.isOneToOneNotOwner)
// throw new Error(`Only many-to-one and one-to-one with join column are supported for this operation. ${this.metadata.name}#${propertyName} relation type is ${relation.relationType}`);
if (relation.isManyToMany)
@ -144,6 +148,8 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
async addToRelation(relationProperty: string|((t: Entity) => string|any), entityId: any, relatedEntityIds: any[]): Promise<void> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
if (!relation.isManyToMany)
throw new Error(`Only many-to-many relation supported for this operation. However ${this.metadata.name}#${propertyPath} relation type is ${relation.relationType}`);
@ -188,7 +194,9 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
*/
async addToInverseRelation(relationProperty: string|((t: Entity) => string|any), relatedEntityId: any, entityIds: any[]): Promise<void> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
const relation = this.metadata.findRelationWithPropertyName(propertyPath);
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
if (!relation.isManyToMany)
throw new Error(`Only many-to-many relation supported for this operation. However ${this.metadata.name}#${propertyPath} relation type is ${relation.relationType}`);
@ -237,6 +245,8 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
async removeFromRelation(relationProperty: string|((t: Entity) => string|any), entityId: any, relatedEntityIds: any[]): Promise<void> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
if (!relation.isManyToMany)
throw new Error(`Only many-to-many relation supported for this operation. However ${this.metadata.name}#${propertyPath} relation type is ${relation.relationType}`);
@ -282,7 +292,9 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
*/
async removeFromInverseRelation(relationProperty: string|((t: Entity) => string|any), relatedEntityId: any, entityIds: any[]): Promise<void> {
const propertyPath = this.metadata.computePropertyPath(relationProperty);
const relation = this.metadata.findRelationWithPropertyName(propertyPath);
const relation = this.metadata.findRelationWithPropertyPath(propertyPath);
if (!relation)
throw new Error(`Relation with property path ${propertyPath} in entity was not found.`);
if (!relation.isManyToMany)
throw new Error(`Only many-to-many relation supported for this operation. However ${this.metadata.name}#${propertyPath} relation type is ${relation.relationType}`);
@ -511,7 +523,10 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
return relationOrName;
const relationPropertyPath = relationOrName instanceof Function ? relationOrName(this.metadata.propertiesMap) : relationOrName;
return this.metadata.findRelationWithPropertyPath(relationPropertyPath);
const relation = this.metadata.findRelationWithPropertyPath(relationPropertyPath);
if (!relation)
throw new Error(`Relation with property path ${relationPropertyPath} in entity was not found.`);
return relation;
}
/**

View File

@ -32,7 +32,7 @@ export class TreeRepository<Entity> extends Repository<Entity> {
*/
findRoots(): Promise<Entity[]> {
const parentPropertyName = this.metadata.treeParentRelation.propertyName;
const parentPropertyName = this.metadata.treeParentRelation!.propertyName;
return this.createQueryBuilder("treeEntity")
.where(`treeEntity.${parentPropertyName} IS NULL`)
.getMany();
@ -149,13 +149,13 @@ export class TreeRepository<Entity> extends Repository<Entity> {
return rawResults.map(rawResult => {
return {
id: rawResult[alias + "_" + this.metadata.primaryColumns[0].databaseName],
parentId: rawResult[alias + "_" + this.metadata.treeParentRelation.joinColumns[0].referencedColumn!.databaseName]
parentId: rawResult[alias + "_" + this.metadata.treeParentRelation!.joinColumns[0].referencedColumn!.databaseName]
};
});
}
protected buildChildrenEntityTree(entity: any, entities: any[], relationMaps: { id: any, parentId: any }[]): void {
const childProperty = this.metadata.treeChildrenRelation.propertyName;
const childProperty = this.metadata.treeChildrenRelation!.propertyName;
const parentEntityId = this.metadata.primaryColumns[0].getEntityValue(entity);
const childRelationMaps = relationMaps.filter(relationMap => relationMap.parentId === parentEntityId);
const childIds = childRelationMaps.map(relationMap => relationMap.id);
@ -166,7 +166,7 @@ export class TreeRepository<Entity> extends Repository<Entity> {
}
protected buildParentEntityTree(entity: any, entities: any[], relationMaps: { id: any, parentId: any }[]): void {
const parentProperty = this.metadata.treeParentRelation.propertyName;
const parentProperty = this.metadata.treeParentRelation!.propertyName;
const entityId = this.metadata.primaryColumns[0].getEntityValue(entity);
const parentRelationMap = relationMaps.find(relationMap => relationMap.id === entityId);
const parentEntity = entities.find(entity => {