mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
refactoring entity metadata builder stuff
This commit is contained in:
parent
39c6ef7eb7
commit
32505c6f47
@ -4,6 +4,10 @@ import {ForeignKeyMetadata} from "../metadata/ForeignKeyMetadata";
|
||||
import {ColumnTypes} from "../metadata/types/ColumnTypes";
|
||||
import {Connection} from "../connection/Connection";
|
||||
|
||||
/**
|
||||
* Creates EntityMetadata for junction tables of the closure entities.
|
||||
* Closure junction tables are tables generated by closure entities.
|
||||
*/
|
||||
export class ClosureJunctionEntityMetadataBuilder {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -17,7 +21,12 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds EntityMetadata for the closure junction of the given closure entity.
|
||||
*/
|
||||
build(parentClosureEntityMetadata: EntityMetadata) {
|
||||
|
||||
// create entity metadata itself
|
||||
const entityMetadata = new EntityMetadata({
|
||||
parentClosureEntityMetadata: parentClosureEntityMetadata,
|
||||
connection: this.connection,
|
||||
@ -28,6 +37,7 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
}
|
||||
});
|
||||
|
||||
// create ancestor and descendant columns for new closure junction table
|
||||
parentClosureEntityMetadata.primaryColumns.forEach(primaryColumn => {
|
||||
entityMetadata.ownColumns.push(new ColumnMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
@ -55,6 +65,7 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
}));
|
||||
});
|
||||
|
||||
// if tree level column was defined by a closure entity then add it to the junction columns as well
|
||||
if (parentClosureEntityMetadata.treeLevelColumn) {
|
||||
entityMetadata.ownColumns.push(new ColumnMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
@ -69,6 +80,7 @@ export class ClosureJunctionEntityMetadataBuilder {
|
||||
}));
|
||||
}
|
||||
|
||||
// create junction table foreign keys
|
||||
entityMetadata.foreignKeys = [
|
||||
new ForeignKeyMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
|
||||
@ -15,7 +15,7 @@ import {RelationJoinColumnBuilder} from "./RelationJoinColumnBuilder";
|
||||
import {Connection} from "../connection/Connection";
|
||||
|
||||
/**
|
||||
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
|
||||
* Builds EntityMetadata objects and all its sub-metadatas.
|
||||
*/
|
||||
export class EntityMetadataBuilder {
|
||||
|
||||
@ -23,8 +23,19 @@ export class EntityMetadataBuilder {
|
||||
// Protected Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Used to build entity metadatas of the junction entities.
|
||||
*/
|
||||
protected junctionEntityMetadataBuilder: JunctionEntityMetadataBuilder;
|
||||
|
||||
/**
|
||||
* Used to build entity metadatas of the closure junction entities.
|
||||
*/
|
||||
protected closureJunctionEntityMetadataBuilder: ClosureJunctionEntityMetadataBuilder;
|
||||
|
||||
/**
|
||||
* Used to build join columns of the relations.
|
||||
*/
|
||||
protected relationJoinColumnBuilder: RelationJoinColumnBuilder;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -239,26 +250,28 @@ export class EntityMetadataBuilder {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates indices for the table of single table inheritance.
|
||||
*/
|
||||
protected createKeysForTableInheritance(entityMetadata: EntityMetadata) {
|
||||
const indexForKey = new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
columns: [entityMetadata.discriminatorColumn],
|
||||
args: {
|
||||
target: entityMetadata.target,
|
||||
unique: false
|
||||
}
|
||||
});
|
||||
entityMetadata.indices.push(indexForKey);
|
||||
|
||||
const indexForKeyWithPrimary = new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
columns: [entityMetadata.primaryColumns[0], entityMetadata.discriminatorColumn],
|
||||
args: {
|
||||
target: entityMetadata.target,
|
||||
unique: false
|
||||
}
|
||||
});
|
||||
entityMetadata.indices.push(indexForKeyWithPrimary);
|
||||
entityMetadata.indices.push(
|
||||
new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
columns: [entityMetadata.discriminatorColumn],
|
||||
args: {
|
||||
target: entityMetadata.target,
|
||||
unique: false
|
||||
}
|
||||
}),
|
||||
new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
columns: [...entityMetadata.primaryColumns, entityMetadata.discriminatorColumn],
|
||||
args: {
|
||||
target: entityMetadata.target,
|
||||
unique: false
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -6,6 +6,10 @@ import {RelationMetadata} from "../metadata/RelationMetadata";
|
||||
import {JoinTableMetadataArgs} from "../metadata-args/JoinTableMetadataArgs";
|
||||
import {Connection} from "../connection/Connection";
|
||||
|
||||
/**
|
||||
* Creates EntityMetadata for junction tables.
|
||||
* Junction tables are tables generated by many-to-many relations.
|
||||
*/
|
||||
export class JunctionEntityMetadataBuilder {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -19,16 +23,19 @@ export class JunctionEntityMetadataBuilder {
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
build(relation: RelationMetadata, joinTable: JoinTableMetadataArgs) {
|
||||
const referencedColumns = this.collectRelationReferencedColumns(relation, joinTable);
|
||||
const inverseReferencedColumns = this.collectRelationInverseReferencedColumns(relation, joinTable);
|
||||
/**
|
||||
* Builds EntityMetadata for the junction of the given many-to-many relation.
|
||||
*/
|
||||
build(relation: RelationMetadata, joinTable: JoinTableMetadataArgs): EntityMetadata {
|
||||
const referencedColumns = this.collectReferencedColumns(relation, joinTable);
|
||||
const inverseReferencedColumns = this.collectInverseReferencedColumns(relation, joinTable);
|
||||
|
||||
const joinTableName = joinTable.name || this.connection.driver.namingStrategy.joinTableName(
|
||||
relation.entityMetadata.tableNameWithoutPrefix,
|
||||
relation.inverseEntityMetadata.tableNameWithoutPrefix,
|
||||
relation.propertyPath,
|
||||
relation.hasInverseSide ? relation.inverseRelation.propertyName : ""
|
||||
);
|
||||
relation.entityMetadata.tableNameWithoutPrefix,
|
||||
relation.inverseEntityMetadata.tableNameWithoutPrefix,
|
||||
relation.propertyPath,
|
||||
relation.hasInverseSide ? relation.inverseRelation.propertyName : ""
|
||||
);
|
||||
|
||||
const entityMetadata = new EntityMetadata({
|
||||
connection: this.connection,
|
||||
@ -38,6 +45,8 @@ export class JunctionEntityMetadataBuilder {
|
||||
type: "junction"
|
||||
}
|
||||
});
|
||||
|
||||
// create original side junction columns
|
||||
const junctionColumns = referencedColumns.map(referencedColumn => {
|
||||
const joinColumn = joinTable.joinColumns ? joinTable.joinColumns.find(joinColumnArgs => {
|
||||
return (!joinColumnArgs.referencedColumnName || joinColumnArgs.referencedColumnName === referencedColumn.propertyName) &&
|
||||
@ -63,6 +72,7 @@ export class JunctionEntityMetadataBuilder {
|
||||
});
|
||||
});
|
||||
|
||||
// create inverse side junction columns
|
||||
const inverseJunctionColumns = inverseReferencedColumns.map(inverseReferencedColumn => {
|
||||
const joinColumn = joinTable.inverseJoinColumns ? joinTable.inverseJoinColumns.find(joinColumnArgs => {
|
||||
return (!joinColumnArgs.referencedColumnName || joinColumnArgs.referencedColumnName === inverseReferencedColumn.propertyName) &&
|
||||
@ -88,6 +98,11 @@ export class JunctionEntityMetadataBuilder {
|
||||
});
|
||||
});
|
||||
|
||||
// set junction table columns
|
||||
entityMetadata.ownColumns = [...junctionColumns, ...inverseJunctionColumns];
|
||||
entityMetadata.ownColumns.forEach(column => column.relationMetadata = relation);
|
||||
|
||||
// create junction table foreign keys
|
||||
entityMetadata.foreignKeys = [
|
||||
new ForeignKeyMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
@ -103,8 +118,7 @@ export class JunctionEntityMetadataBuilder {
|
||||
}),
|
||||
];
|
||||
|
||||
junctionColumns.concat(inverseJunctionColumns).forEach(column => column.relationMetadata = relation);
|
||||
entityMetadata.ownColumns = junctionColumns.concat(inverseJunctionColumns);
|
||||
// create junction table indices
|
||||
entityMetadata.indices = [
|
||||
new IndexMetadata({
|
||||
entityMetadata: entityMetadata,
|
||||
@ -125,6 +139,7 @@ export class JunctionEntityMetadataBuilder {
|
||||
})
|
||||
];
|
||||
|
||||
// finally return entity metadata
|
||||
return entityMetadata;
|
||||
}
|
||||
|
||||
@ -132,7 +147,10 @@ export class JunctionEntityMetadataBuilder {
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected collectRelationReferencedColumns(relation: RelationMetadata, joinTable: JoinTableMetadataArgs) {
|
||||
/**
|
||||
* Collects referenced columns from the given join column args.
|
||||
*/
|
||||
protected collectReferencedColumns(relation: RelationMetadata, joinTable: JoinTableMetadataArgs) {
|
||||
const hasAnyReferencedColumnName = joinTable.joinColumns ? joinTable.joinColumns.find(joinColumn => !!joinColumn.referencedColumnName) : false;
|
||||
if (!joinTable.joinColumns || (joinTable.joinColumns && !hasAnyReferencedColumnName)) {
|
||||
return relation.entityMetadata.ownColumns.filter(column => column.isPrimary);
|
||||
@ -147,7 +165,10 @@ export class JunctionEntityMetadataBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
protected collectRelationInverseReferencedColumns(relation: RelationMetadata, joinTable: JoinTableMetadataArgs) {
|
||||
/**
|
||||
* Collects inverse referenced columns from the given join column args.
|
||||
*/
|
||||
protected collectInverseReferencedColumns(relation: RelationMetadata, joinTable: JoinTableMetadataArgs) {
|
||||
const hasInverseJoinColumns = !!joinTable.inverseJoinColumns;
|
||||
const hasAnyInverseReferencedColumnName = hasInverseJoinColumns ? joinTable.inverseJoinColumns!.find(joinColumn => !!joinColumn.referencedColumnName) : false;
|
||||
if (!hasInverseJoinColumns || (hasInverseJoinColumns && !hasAnyInverseReferencedColumnName)) {
|
||||
|
||||
@ -4,28 +4,36 @@ import {RelationMetadata} from "../metadata/RelationMetadata";
|
||||
import {JoinColumnMetadataArgs} from "../metadata-args/JoinColumnMetadataArgs";
|
||||
import {Connection} from "../connection/Connection";
|
||||
|
||||
// cases it should cover:
|
||||
// 1. when join column is set with custom name and without referenced column name
|
||||
// we need automatically set referenced column name - primary ids by default
|
||||
// @JoinColumn({ name: "custom_name" })
|
||||
// 2. when join column is set with only referenced column name
|
||||
// we need automatically set join column name - relation name + referenced column name
|
||||
// @JoinColumn({ referencedColumnName: "title" })
|
||||
// 3. when join column is set without both referenced column name and join column name
|
||||
// we need to automatically set both of them
|
||||
// @JoinColumn()
|
||||
// 4. when join column is not set at all (as in case of @ManyToOne relation)
|
||||
// we need to create join column for it with proper referenced column name and join column name
|
||||
// 5. when multiple join columns set none of referencedColumnName and name can be optional
|
||||
// both options are required
|
||||
// @JoinColumn([
|
||||
// { name: "category_title", referencedColumnName: "type" },
|
||||
// { name: "category_title", referencedColumnName: "name" },
|
||||
// ])
|
||||
|
||||
// since for many-to-one relations having JoinColumn decorator is not required,
|
||||
// we need to go thought each many-to-one relation without join column decorator set
|
||||
// and create join column metadata args for them
|
||||
/**
|
||||
* Builds join column for the many-to-one and one-to-one owner relations.
|
||||
*
|
||||
* Cases it should cover:
|
||||
* 1. when join column is set with custom name and without referenced column name
|
||||
* we need automatically set referenced column name - primary ids by default
|
||||
* @JoinColumn({ name: "custom_name" })
|
||||
*
|
||||
* 2. when join column is set with only referenced column name
|
||||
* we need automatically set join column name - relation name + referenced column name
|
||||
* @JoinColumn({ referencedColumnName: "title" })
|
||||
*
|
||||
* 3. when join column is set without both referenced column name and join column name
|
||||
* we need to automatically set both of them
|
||||
* @JoinColumn()
|
||||
*
|
||||
* 4. when join column is not set at all (as in case of @ManyToOne relation)
|
||||
* we need to create join column for it with proper referenced column name and join column name
|
||||
*
|
||||
* 5. when multiple join columns set none of referencedColumnName and name can be optional
|
||||
* both options are required
|
||||
* @JoinColumn([
|
||||
* { name: "category_title", referencedColumnName: "type" },
|
||||
* { name: "category_title", referencedColumnName: "name" },
|
||||
* ])
|
||||
*
|
||||
* Since for many-to-one relations having JoinColumn decorator is not required,
|
||||
* we need to go thought each many-to-one relation without join column decorator set
|
||||
* and create join column metadata args for them.
|
||||
*/
|
||||
export class RelationJoinColumnBuilder {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -39,12 +47,15 @@ export class RelationJoinColumnBuilder {
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Builds a foreign key of the many-to-one or one-to-one owner relations.
|
||||
*/
|
||||
build(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata): ForeignKeyMetadata|undefined {
|
||||
const referencedColumns = this.collectRelationReferencedColumns(joinColumns, relation);
|
||||
const referencedColumns = this.collectReferencedColumns(joinColumns, relation);
|
||||
if (!referencedColumns.length)
|
||||
return undefined; // this case is possible only for one-to-one non owning side
|
||||
|
||||
const columns = this.collectRelationColumns(joinColumns, relation, referencedColumns);
|
||||
const columns = this.collectColumns(joinColumns, relation, referencedColumns);
|
||||
return new ForeignKeyMetadata({
|
||||
entityMetadata: relation.entityMetadata,
|
||||
referencedEntityMetadata: relation.inverseEntityMetadata,
|
||||
@ -58,7 +69,10 @@ export class RelationJoinColumnBuilder {
|
||||
// Protected Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
protected collectRelationReferencedColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata): ColumnMetadata[] {
|
||||
/**
|
||||
* Collects referenced columns from the given join column args.
|
||||
*/
|
||||
protected collectReferencedColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata): ColumnMetadata[] {
|
||||
const hasAnyReferencedColumnName = joinColumns.find(joinColumnArgs => !!joinColumnArgs.referencedColumnName);
|
||||
const manyToOneWithoutJoinColumn = joinColumns.length === 0 && relation.isManyToOne;
|
||||
const hasJoinColumnWithoutAnyReferencedColumnName = joinColumns.length > 0 && !hasAnyReferencedColumnName;
|
||||
@ -77,7 +91,10 @@ export class RelationJoinColumnBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
private collectRelationColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata, referencedColumns: ColumnMetadata[]): ColumnMetadata[] {
|
||||
/**
|
||||
* Collects columns from the given join column args.
|
||||
*/
|
||||
private collectColumns(joinColumns: JoinColumnMetadataArgs[], relation: RelationMetadata, referencedColumns: ColumnMetadata[]): ColumnMetadata[] {
|
||||
return referencedColumns.map(referencedColumn => {
|
||||
|
||||
// in the case if relation has join column with only name set we need this check
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user