added custom join table names

This commit is contained in:
Umed Khudoiberdiev 2016-05-04 17:39:59 +05:00
parent e4647748c3
commit 6856af143d
22 changed files with 304 additions and 68 deletions

View File

@ -1,7 +1,7 @@
{
"name": "typeorm",
"private": true,
"version": "0.0.2-alpha.9",
"version": "0.0.2-alpha.10",
"description": "Data-mapper ORM for Typescript",
"license": "Apache-2.0",
"readmeFilename": "README.md",

View File

@ -24,4 +24,19 @@ export class CustomNamingStrategy implements NamingStrategyInterface {
return "index" + columns.join("_");
}
joinColumnInverseSideName(joinColumnName: string, propertyName: string): string {
if (joinColumnName)
return joinColumnName;
return propertyName;
}
joinTableName(firstTableName: string, secondTableName: string, firstColumnName: string, secondColumnName: string): string {
return firstTableName + "_" + firstColumnName + "_" + secondTableName + "_" + secondColumnName;
}
joinTableColumnName(tableName: string, columnName: string): string {
return tableName + "_" + columnName;
}
}

View File

@ -27,15 +27,26 @@ createConnection(options).then(connection => {
let author = new Author();
author.name = "Umed";
let category1 = new Category();
category1.name = "Category #1";
let category2 = new Category();
category2.name = "Category #2";
let post = new Post();
post.text = "Hello how are you?";
post.title = "hello";
post.author = author;
post.categories = [category1, category2];
postRepository
.persist(post)
.then(post => {
console.log("Post has been saved.");
console.log("Post has been saved. Lets load it now.");
return postRepository.find({ alias: "post", leftJoinAndSelect: { categories: "post.categories"} });
})
.then(loadedPosts => {
console.log("loadedPosts: ", loadedPosts);
})
.catch(error => console.log(error.stack));

View File

@ -22,9 +22,9 @@ export class Post {
@ManyToOne(type => Author, author => author.posts, {
cascadeAll: true
})
@JoinColumn({
@JoinColumn(/*{ // todo: not yet fixed
name: "user"
})
}*/)
author: Author;
@ManyToMany(type => Category, category => category.posts, {

View File

@ -17,6 +17,10 @@ import {IndexMetadata} from "../metadata/IndexMetadata";
import {CompositeIndexMetadata} from "../metadata/CompositeIndexMetadata";
import {PropertyMetadataCollection} from "../metadata/collection/PropertyMetadataCollection";
import {TargetMetadataCollection} from "../metadata/collection/TargetMetadataCollection";
import {JoinTableMetadata} from "../metadata/JoinTableMetadata";
import {JoinTableOptions} from "../metadata/options/JoinTableOptions";
import {JoinColumnMetadata} from "../metadata/JoinColumnMetadata";
import {JoinColumnOptions} from "../metadata/options/JoinColumnOptions";
/**
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
@ -91,19 +95,35 @@ export class EntityMetadataBuilder {
mergedMetadata.relationMetadatas,
mergedMetadata.compositeIndexMetadatas
);
entityMetadata.namingStrategy = this.namingStrategy;
// find entity's relations join tables
entityMetadata.relations.forEach(relation => {
// create entity's relations join tables
entityMetadata.manyToManyRelations.forEach(relation => {
const joinTable = mergedMetadata.joinTableMetadatas.findByProperty(relation.propertyName);
if (joinTable)
if (joinTable) {
relation.joinTable = joinTable;
joinTable.relation = relation;
}
});
// find entity's relations join columns
// create entity's relations join columns
entityMetadata.relations.forEach(relation => {
const joinColumn = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
if (joinColumn)
if (joinColumn) {
relation.joinColumn = joinColumn;
joinColumn.relation = relation;
}
});
// since for many-to-one relations having JoinColumn is not required on decorators level, we need to go
// throw all of them which don't have JoinColumn decorators and create it for them
entityMetadata.manyToOneRelations.forEach(relation => {
let joinColumn = mergedMetadata.joinColumnMetadatas.findByProperty(relation.propertyName);
if (!joinColumn) {
joinColumn = new JoinColumnMetadata(relation.target, relation.propertyName, <JoinColumnOptions> {});
relation.joinColumn = joinColumn;
joinColumn.relation = relation;
}
});
return entityMetadata;
@ -112,7 +132,7 @@ export class EntityMetadataBuilder {
// after all metadatas created we set inverse side (related) entity metadatas for all relation metadatas
entityMetadatas.forEach(entityMetadata => {
entityMetadata.relations.forEach(relation => {
relation.relatedEntityMetadata = entityMetadatas.find(m => m.target === relation.type);
relation.inverseEntityMetadata = entityMetadatas.find(m => m.target === relation.type);
});
});
@ -124,11 +144,12 @@ export class EntityMetadataBuilder {
metadata.relationsWithJoinColumns.forEach(relation => {
// find relational column and if it does not exist - add it
const inverseSideColumn = relation.relatedEntityMetadata.primaryColumn;
// todo: later add support for propertyInFunction
const inverseSideColumn = relation.joinColumn.referencedColumn;
let relationalColumn = metadata.columns.find(column => column.name === relation.name); // todo?: ColumnCollection.findByName
if (!relationalColumn) {
const options: ColumnOptions = {
name: relation.joinColumn.name,
type: inverseSideColumn.type,
oldColumnName: relation.oldColumnName,
nullable: relation.isNullable
@ -147,7 +168,7 @@ export class EntityMetadataBuilder {
const foreignKey = new ForeignKeyMetadata(
metadata.table,
[relationalColumn],
relation.relatedEntityMetadata.table,
relation.inverseEntityMetadata.table,
[inverseSideColumn],
relation.onDelete
);
@ -159,36 +180,44 @@ export class EntityMetadataBuilder {
const junctionEntityMetadatas: EntityMetadata[] = [];
entityMetadatas.forEach(metadata => {
metadata.ownerManyToManyRelations.map(relation => {
const inverseSideMetadata = entityMetadatas.find(metadata => metadata.target === relation.type);
const tableName = metadata.table.name + "_" + relation.name + "_" +
inverseSideMetadata.table.name + "_" + inverseSideMetadata.primaryColumn.name;
const inverseSideMetadata = relation.inverseEntityMetadata;
// const inverseSideColumn = relation.inverseSideColumn;
// generate table name for junction table
/*const tableName = this.namingStrategy.joinTableName(
metadata.table.name,
inverseSideMetadata.table.name,
relation.name,
inverseSideColumn.name
);*/
const tableMetadata = new JunctionTableMetadata(relation.joinTable.name);
const column1 = relation.joinTable.referencedColumn;
const column2 = relation.joinTable.inverseReferencedColumn;
const tableMetadata = new JunctionTableMetadata(tableName);
const column1options: ColumnOptions = {
length: metadata.primaryColumn.length,
type: metadata.primaryColumn.type,
name: metadata.table.name + "_" + metadata.primaryColumn.name + "_1"
length: column1.length,
type: column1.type,
name: relation.joinTable.joinColumnName // metadata.table.name + "_" + column1.name
};
const column2options: ColumnOptions = {
length: inverseSideMetadata.primaryColumn.length,
type: inverseSideMetadata.primaryColumn.type,
name: inverseSideMetadata.table.name + "_" + inverseSideMetadata.primaryColumn.name + "_2"
length: column2.length,
type: column2.type,
name: relation.joinTable.inverseJoinColumnName // inverseSideMetadata.table.name + "_" + column2.name
};
const columns = [
new ColumnMetadata({
propertyType: inverseSideMetadata.primaryColumn.type,
propertyType: column2.type,
options: column1options
}),
new ColumnMetadata({
propertyType: inverseSideMetadata.primaryColumn.type,
propertyType: column2.type,
options: column2options
})
];
const junctionEntityMetadata = new EntityMetadata(tableMetadata, columns, [], []);
junctionEntityMetadata.foreignKeys.push(
new ForeignKeyMetadata(tableMetadata, [columns[0]], metadata.table, [metadata.primaryColumn]),
new ForeignKeyMetadata(tableMetadata, [columns[1]], inverseSideMetadata.table, [inverseSideMetadata.primaryColumn])
new ForeignKeyMetadata(tableMetadata, [columns[0]], metadata.table, [column1]),
new ForeignKeyMetadata(tableMetadata, [columns[1]], inverseSideMetadata.table, [column2])
);
junctionEntityMetadatas.push(junctionEntityMetadata);
relation.junctionEntityMetadata = junctionEntityMetadata;

View File

@ -11,7 +11,7 @@ export class MissingJoinColumnError extends Error {
super();
if (relation.inverseRelation) {
this.message = `JoinColumn is missing on both sides of ${entityMetadata.name}#${relation.name} and ` +
`${relation.relatedEntityMetadata.name}#${relation.inverseRelation.name} one-to-one relationship. ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} one-to-one relationship. ` +
`You need to put JoinColumn decorator on one of the sides.`;
} else {
this.message = `JoinColumn is missing on ${entityMetadata.name}#${relation.name} one-to-one relationship. ` +

View File

@ -12,7 +12,7 @@ export class MissingJoinTableError extends Error {
if (relation.inverseRelation) {
this.message = `JoinTable is missing on both sides of ${entityMetadata.name}#${relation.name} and ` +
`${relation.relatedEntityMetadata.name}#${relation.inverseRelation.name} many-to-many relationship. ` +
`${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} many-to-many relationship. ` +
`You need to put decorator decorator on one of the sides.`;
} else {
this.message = `JoinTable is missing on ${entityMetadata.name}#${relation.name} many-to-many relationship. ` +

View File

@ -10,7 +10,7 @@ export class UsingJoinColumnOnlyOnOneSideAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinColumn is allowed only on one side of the one-to-one relationship. ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.relatedEntityMetadata.name}#${relation.inverseRelation.name} ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} ` +
`has JoinTable decorators. Choose one of them and left JoinTable decorator only on it.`;
}

View File

@ -10,7 +10,7 @@ export class UsingJoinTableOnlyOnOneSideAllowedError extends Error {
constructor(entityMetadata: EntityMetadata, relation: RelationMetadata) {
super();
this.message = `Using JoinTable is allowed only on one side of the many-to-many relationship. ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.relatedEntityMetadata.name}#${relation.inverseRelation.name} ` +
`Both ${entityMetadata.name}#${relation.name} and ${relation.inverseEntityMetadata.name}#${relation.inverseRelation.name} ` +
`has JoinTable decorators. Choose one of them and left JoinColumn decorator only on it.`;
}

View File

@ -1,16 +1,25 @@
import {TableMetadata} from "./TableMetadata";
import {ColumnMetadata} from "./ColumnMetadata";
import {RelationMetadata} from "./RelationMetadata";
import {IndexMetadata} from "./IndexMetadata";
import {CompositeIndexMetadata} from "./CompositeIndexMetadata";
import {RelationTypes} from "./types/RelationTypes";
import {ForeignKeyMetadata} from "./ForeignKeyMetadata";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
/**
* Contains all entity metadata.
*/
export class EntityMetadata {
// ---------------------------------------------------------------------
// Public Properties
// ---------------------------------------------------------------------
/**
* Naming strategy used to generate and normalize column name.
*/
namingStrategy: NamingStrategyInterface;
// -------------------------------------------------------------------------
// Readonly Properties
// -------------------------------------------------------------------------
@ -34,7 +43,7 @@ export class EntityMetadata {
this.relations = relations;
this.compositeIndices = compositeIndices;
// this.relations.forEach(relation => relation.entityMetadata = this);
this.relations.forEach(relation => relation.entityMetadata = this);
this.compositeIndices.forEach(index => index.entityMetadata = this);
}

View File

@ -1,5 +1,8 @@
import {PropertyMetadata} from "./PropertyMetadata";
import {JoinColumnOptions} from "./options/JoinColumnOptions";
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategy";
import {RelationMetadata} from "./RelationMetadata";
import {ColumnMetadata} from "./ColumnMetadata";
/**
*/
@ -10,26 +13,58 @@ export class JoinColumnMetadata extends PropertyMetadata {
// ---------------------------------------------------------------------
/**
* Naming strategy used to generate and normalize column name.
* Relation - owner of this join column metadata.
*/
// namingStrategy: NamingStrategyInterface;
relation: RelationMetadata;
// ---------------------------------------------------------------------
// Readonly Properties
// ---------------------------------------------------------------------
/**
* Join table options.
* Join column name.
*/
readonly options: JoinColumnOptions;
private readonly _name: string;
/**
* Join column referenced column name.
*/
private readonly _referencedColumnName: string;
// ---------------------------------------------------------------------
// Constructor
// ---------------------------------------------------------------------
constructor(target: Function, propertyName: string, options: JoinColumnOptions) {
constructor(target: Function,
propertyName: string,
options: JoinColumnOptions) {
super(target, propertyName);
this.options = options;
if (options.name)
this._name = options.name;
if (options.referencedColumnName)
this._referencedColumnName = options.referencedColumnName;
}
// ---------------------------------------------------------------------
// Accessors
// ---------------------------------------------------------------------
/**
* Join column name.
*/
get name() {
return this.relation.entityMetadata.namingStrategy.joinColumnInverseSideName(this._name, this.relation.propertyName);
}
/**
* Referenced join column.
*/
get referencedColumn(): ColumnMetadata {
if (this._referencedColumnName)
return this.relation.inverseEntityMetadata.columns.find(column => column.name === this._referencedColumnName);
return this.relation.inverseEntityMetadata.primaryColumn;
}
}

View File

@ -1,5 +1,7 @@
import {PropertyMetadata} from "./PropertyMetadata";
import {JoinTableOptions} from "./options/JoinTableOptions";
import {RelationMetadata} from "./RelationMetadata";
import {ColumnMetadata} from "./ColumnMetadata";
/**
*/
@ -10,18 +12,38 @@ export class JoinTableMetadata extends PropertyMetadata {
// ---------------------------------------------------------------------
/**
* Naming strategy used to generate and normalize column name.
* Relation - owner of this join table metadata.
*/
// namingStrategy: NamingStrategyInterface;
relation: RelationMetadata;
// ---------------------------------------------------------------------
// Readonly Properties
// ---------------------------------------------------------------------
/**
* Join table options.
* Join table name.
*/
readonly options: JoinTableOptions;
private readonly _name: string;
/**
* Join column name.
*/
private readonly _joinColumnName: string;
/**
* Join column referenced column name.
*/
private readonly _joinColumnReferencedColumnName: string;
/**
* Join column name of the inverse side.
*/
private readonly _inverseJoinColumnName: string;
/**
* Join column referenced column name of the inverse side.
*/
private readonly _inverseJoinColumnReferencedColumnName: string;
// ---------------------------------------------------------------------
// Constructor
@ -29,7 +51,82 @@ export class JoinTableMetadata extends PropertyMetadata {
constructor(target: Function, propertyName: string, options: JoinTableOptions) {
super(target, propertyName);
this.options = options;
if (options.name)
this._name = options.name;
if (options.joinColumn) {
if (options.joinColumn.name)
this._joinColumnName = options.joinColumn.name;
if (options.joinColumn.referencedColumnName)
this._joinColumnReferencedColumnName = options.joinColumn.referencedColumnName;
}
if (options.inverseJoinColumn) {
if (options.inverseJoinColumn.name)
this._inverseJoinColumnName = options.inverseJoinColumn.name;
if (options.inverseJoinColumn.referencedColumnName)
this._inverseJoinColumnReferencedColumnName = options.inverseJoinColumn.referencedColumnName;
}
}
// ---------------------------------------------------------------------
// Accessors
// ---------------------------------------------------------------------
/**
* Join table name.
*/
get name() {
if (this._name)
return this._name;
return this.relation.entityMetadata.namingStrategy.joinTableName(
this.relation.entityMetadata.table.name,
this.relation.inverseEntityMetadata.table.name,
this.referencedColumn.name,
this.inverseReferencedColumn.name
);
}
/**
* Join column name.
*/
get joinColumnName() {
if (this._joinColumnName)
return this._joinColumnName;
return this.relation.entityMetadata.namingStrategy.joinTableColumnName(this.relation.entityMetadata.table.name, this.referencedColumn.name);
}
/**
* Join column name of the inverse side.
*/
get inverseJoinColumnName() {
if (this._inverseJoinColumnName)
return this._inverseJoinColumnName;
return this.relation.entityMetadata.namingStrategy.joinTableColumnName(this.relation.inverseEntityMetadata.table.name, this.inverseReferencedColumn.name);
}
/**
* Referenced join column.
*/
get referencedColumn(): ColumnMetadata {
if (this._joinColumnReferencedColumnName)
return this.relation.entityMetadata.columns.find(column => column.name === this._joinColumnReferencedColumnName);
return this.relation.entityMetadata.primaryColumn;
}
/**
* Referenced join column of the inverse side.
*/
get inverseReferencedColumn(): ColumnMetadata {
if (this._joinColumnReferencedColumnName)
return this.relation.inverseEntityMetadata.columns.find(column => column.name === this._inverseJoinColumnReferencedColumnName);
return this.relation.inverseEntityMetadata.primaryColumn;
}
}

View File

@ -6,6 +6,7 @@ import {OnDeleteType} from "./ForeignKeyMetadata";
import {JoinTableMetadata} from "./JoinTableMetadata";
import {JoinColumnMetadata} from "./JoinColumnMetadata";
import {RelationMetadataArgs} from "./args/RelationMetadataArgs";
import {ColumnMetadata} from "./ColumnMetadata";
/**
* Function that returns a type of the field. Returned value must be a class used on the relation.
@ -32,10 +33,15 @@ export class RelationMetadata extends PropertyMetadata {
*/
namingStrategy: NamingStrategyInterface;
/**
* Its own entity metadata.
*/
entityMetadata: EntityMetadata;
/**
* Related entity metadata.
*/
relatedEntityMetadata: EntityMetadata;
inverseEntityMetadata: EntityMetadata;
/**
* Junction entity metadata.
@ -173,7 +179,7 @@ export class RelationMetadata extends PropertyMetadata {
}
get inverseRelation(): RelationMetadata {
return this.relatedEntityMetadata.findRelationWithPropertyName(this.computeInverseSide(this._inverseSideProperty));
return this.inverseEntityMetadata.findRelationWithPropertyName(this.computeInverseSide(this._inverseSideProperty));
}
get isOneToOne(): boolean {
@ -193,7 +199,7 @@ export class RelationMetadata extends PropertyMetadata {
}
get hasInverseSide(): boolean {
return this.relatedEntityMetadata && !!this.inverseRelation;
return this.inverseEntityMetadata && !!this.inverseRelation;
}
get isLazy(): boolean {
@ -205,7 +211,7 @@ export class RelationMetadata extends PropertyMetadata {
// ---------------------------------------------------------------------
private computeInverseSide(inverseSide: PropertyTypeInFunction<any>): string {
const ownerEntityPropertiesMap = this.relatedEntityMetadata.createPropertiesMap();
const ownerEntityPropertiesMap = this.inverseEntityMetadata.createPropertiesMap();
if (typeof inverseSide === "function")
return (<Function> inverseSide)(ownerEntityPropertiesMap);
if (typeof inverseSide === "string")

View File

@ -24,5 +24,20 @@ export class DefaultNamingStrategy implements NamingStrategyInterface {
return "ind_" + columns.join("_");
}
joinColumnInverseSideName(joinColumnName: string, propertyName: string): string {
if (joinColumnName)
return joinColumnName;
return propertyName;
}
joinTableName(firstTableName: string, secondTableName: string, firstColumnName: string, secondColumnName: string): string {
return firstTableName + "_" + firstColumnName + "_" + secondTableName + "_" + secondColumnName;
}
joinTableColumnName(tableName: string, columnName: string): string {
return tableName + "_" + columnName;
}
}

View File

@ -24,4 +24,19 @@ export interface NamingStrategyInterface {
*/
indexName(target: Function, name: string, columns: string[]): string;
/**
* Gets the name of the join column used in the one-to-one and many-to-one relations.
*/
joinColumnInverseSideName(joinColumnName: string|undefined, propertyName: string): string;
/**
* Gets the name of the join table used in the many-to-many relations.
*/
joinTableName(firstTableName: string, secondTableName: string, firstColumnName: string, secondColumnName: string): string;
/**
* Gets the name of the column used for columns in the junction tables.
*/
joinTableColumnName(tableName: string, columnName: string): string;
}

View File

@ -153,7 +153,7 @@ export class EntityPersistOperationBuilder {
}
metadata.relations.forEach(relation => {
const relMetadata = relation.relatedEntityMetadata;
const relMetadata = relation.inverseEntityMetadata;
const relationIdColumnName = relMetadata.primaryColumn.name;
const value = this.getEntityRelationValue(relation, newEntity);
const dbValue = this.getEntityRelationValue(relation, dbEntity);
@ -203,7 +203,7 @@ export class EntityPersistOperationBuilder {
metadata.relations.forEach(relation => {
const dbValue = this.getEntityRelationValue(relation, dbEntity);
const relMetadata = relation.relatedEntityMetadata;
const relMetadata = relation.inverseEntityMetadata;
if (!dbValue) return;
if (dbValue instanceof Array) {
@ -275,7 +275,7 @@ export class EntityPersistOperationBuilder {
.filter(relation => relation.isManyToMany)
// .filter(relation => newEntity[relation.propertyName] instanceof Array)
.reduce((operations, relation) => {
const relationMetadata = relation.relatedEntityMetadata;
const relationMetadata = relation.inverseEntityMetadata;
const relationIdProperty = relationMetadata.primaryColumn.name;
const value = this.getEntityRelationValue(relation, newEntity);
const dbValue = dbEntity ? this.getEntityRelationValue(relation, dbEntity.entity) : null;
@ -313,7 +313,7 @@ export class EntityPersistOperationBuilder {
.filter(relation => relation.isManyToMany)
// .filter(relation => dbEntity[relation.propertyName] instanceof Array)
.reduce((operations, relation) => {
const relationMetadata = relation.relatedEntityMetadata;
const relationMetadata = relation.inverseEntityMetadata;
const relationIdProperty = relationMetadata.primaryColumn.name;
const value = newEntity ? this.getEntityRelationValue(relation, newEntity.entity) : null;
const dbValue = this.getEntityRelationValue(relation, dbEntity);

View File

@ -296,16 +296,16 @@ export class PersistOperationExecutor {
.filter(column => entity.hasOwnProperty(column.propertyName))
.map(column => this.driver.preparePersistentValue(entity[column.propertyName], column));
const relationColumns = metadata.relations
.filter(relation => relation.isOwning && !!relation.relatedEntityMetadata)
.filter(relation => relation.isOwning && !!relation.inverseEntityMetadata)
.filter(relation => entity.hasOwnProperty(relation.propertyName))
.filter(relation => entity[relation.propertyName][relation.relatedEntityMetadata.primaryColumn.name])
.filter(relation => entity[relation.propertyName][relation.inverseEntityMetadata.primaryColumn.name])
.map(relation => relation.name);
const relationValues = metadata.relations
.filter(relation => relation.isOwning && !!relation.relatedEntityMetadata)
.filter(relation => relation.isOwning && !!relation.inverseEntityMetadata)
.filter(relation => entity.hasOwnProperty(relation.propertyName))
.filter(relation => entity[relation.propertyName].hasOwnProperty(relation.relatedEntityMetadata.primaryColumn.name))
.map(relation => entity[relation.propertyName][relation.relatedEntityMetadata.primaryColumn.name]);
.filter(relation => entity[relation.propertyName].hasOwnProperty(relation.inverseEntityMetadata.primaryColumn.name))
.map(relation => entity[relation.propertyName][relation.inverseEntityMetadata.primaryColumn.name]);
const allColumns = columns.concat(relationColumns);
const allValues = values.concat(relationValues);

View File

@ -577,29 +577,33 @@ export class QueryBuilder<Entity> {
const relation = parentMetadata.findRelationWithDbName(join.alias.parentPropertyName);
const junctionMetadata = relation.junctionEntityMetadata;
const joinMetadata = this.aliasMap.getEntityMetadataByAlias(join.alias);
const joinTable = joinMetadata.table.name;
const joinTableColumn = joinMetadata.primaryColumn.name;
const joinTableName = joinMetadata.table.name;
if (relation.isManyToMany) {
const junctionTable = junctionMetadata.table.name;
const junctionAlias = join.alias.parentAliasName + "_" + join.alias.name;
const joinAlias = join.alias.name;
const joinTable = relation.isOwning ? relation.joinTable : relation.inverseRelation.joinTable; // not sure if this is correct
const joinTableColumn = joinTable.referencedColumn.name; // not sure if this is correct
const inverseJoinColumnName = joinTable.inverseReferencedColumn.name; // not sure if this is correct
const condition1 = junctionAlias + "." + junctionMetadata.columns[0].name + "=" + parentAlias + "." + joinTableColumn; // todo: use column names from junction table somehow
const condition2 = joinAlias + "." + joinTableColumn + "=" + junctionAlias + "." + junctionMetadata.columns[1].name;
const condition2 = joinAlias + "." + inverseJoinColumnName + "=" + junctionAlias + "." + junctionMetadata.columns[1].name;
return " " + joinType + " JOIN " + junctionTable + " " + junctionAlias + " " + join.conditionType + " " + condition1 +
" " + joinType + " JOIN " + joinTable + " " + joinAlias + " " + join.conditionType + " " + condition2 + appendedCondition;
" " + joinType + " JOIN " + joinTableName + " " + joinAlias + " " + join.conditionType + " " + condition2 + appendedCondition;
} else if (relation.isManyToOne || (relation.isOneToOne && relation.isOwning)) {
const joinTableColumn = relation.joinColumn.referencedColumn.name;
const condition = join.alias.name + "." + joinTableColumn + "=" + parentAlias + "." + join.alias.parentPropertyName;
return " " + joinType + " JOIN " + joinTable + " " + join.alias.name + " " + join.conditionType + " " + condition + appendedCondition;
return " " + joinType + " JOIN " + joinTableName + " " + join.alias.name + " " + join.conditionType + " " + condition + appendedCondition;
} else if (relation.isOneToMany || (relation.isOneToOne && !relation.isOwning)) {
const joinTableColumn = relation.inverseRelation.joinColumn.referencedColumn.name;
const condition = join.alias.name + "." + relation.inverseSideProperty + "=" + parentAlias + "." + joinTableColumn;
return " " + joinType + " JOIN " + joinTable + " " + join.alias.name + " " + join.conditionType + " " + condition + appendedCondition;
return " " + joinType + " JOIN " + joinTableName + " " + join.alias.name + " " + join.conditionType + " " + condition + appendedCondition;
} else {
return " " + joinType + " JOIN " + joinTable + " " + join.alias.name + " " + join.conditionType + " " + join.condition;
return " " + joinType + " JOIN " + joinTableName + " " + join.alias.name + " " + join.conditionType + " " + join.condition;
}
}).join(" ");
}

View File

@ -61,7 +61,7 @@ export class AliasMap {
if (!relation)
throw new Error("Relation metadata for " + alias.parentAliasName + "#" + alias.parentPropertyName + " was not found.");
return relation.relatedEntityMetadata;
return relation.inverseEntityMetadata;
}
throw new Error("Cannot get entity metadata for the given alias " + alias.name);

View File

@ -67,7 +67,7 @@ export class PlainObjectToDatabaseEntityTransformer<Entity> {
if (value instanceof Array)
value = Object.assign({}, ...value);
const child = value ? this.buildLoadMap(value, relation.relatedEntityMetadata) : [];
const child = value ? this.buildLoadMap(value, relation.inverseEntityMetadata) : [];
return <LoadMap> { name: relation.name, child: child };
});
}

View File

@ -43,7 +43,7 @@ export class PlainObjectToNewEntityTransformer {
metadata.relations
.filter(relation => object.hasOwnProperty(relation.propertyName))
.forEach(relation => {
const relationMetadata = relation.relatedEntityMetadata;
const relationMetadata = relation.inverseEntityMetadata;
if (!relationMetadata)
throw new Error("Relation metadata for the relation " + (<any> metadata.target).name + "#" + relation.propertyName + " is missing");

View File

@ -329,7 +329,7 @@ export class Repository<Entity> {
const promises = metadata.relations
// .filter(relation => !!entity[relation.propertyName])
.map(relation => {
const relMetadata = relation.relatedEntityMetadata;
const relMetadata = relation.inverseEntityMetadata;
// const value = ;
const value = (entity[relation.propertyName] instanceof Promise && relation.isLazy) ? entity["__" + relation.propertyName + "__"] : entity[relation.propertyName];