multiple primary keys test coverage

This commit is contained in:
Zotov Dmitry 2017-04-27 12:22:54 +05:00
parent c9280ed21c
commit ad2bc865ed
25 changed files with 2530 additions and 127 deletions

View File

@ -3,7 +3,7 @@ import {JoinColumnOptions} from "./JoinColumnOptions";
/**
* Describes all relation's options.
*/
export interface JoinTableMuplipleColumnsOptions {
export interface JoinTableMultipleColumnsOptions {
/**
* Name of the table that will be created to store values of the both tables (join table).

View File

@ -1,7 +1,7 @@
import {getMetadataArgsStorage} from "../../index";
import {JoinTableOptions} from "../options/JoinTableOptions";
import {JoinTableMetadataArgs} from "../../metadata-args/JoinTableMetadataArgs";
import {JoinTableMuplipleColumnsOptions} from "../options/JoinTableMuplipleColumnsOptions";
import {JoinTableMultipleColumnsOptions} from "../options/JoinTableMuplipleColumnsOptions";
/**
* JoinTable decorator is used in many-to-many relationship to specify owner side of relationship.
@ -19,21 +19,21 @@ export function JoinTable(options: JoinTableOptions): Function;
* JoinTable decorator is used in many-to-many relationship to specify owner side of relationship.
* Its also used to set a custom junction table's name, column names and referenced columns.
*/
export function JoinTable(options: JoinTableMuplipleColumnsOptions): Function;
export function JoinTable(options: JoinTableMultipleColumnsOptions): Function;
/**
* JoinTable decorator is used in many-to-many relationship to specify owner side of relationship.
* Its also used to set a custom junction table's name, column names and referenced columns.
*/
export function JoinTable(options?: JoinTableOptions|JoinTableMuplipleColumnsOptions): Function {
export function JoinTable(options?: JoinTableOptions|JoinTableMultipleColumnsOptions): Function {
return function (object: Object, propertyName: string) {
options = options || {} as JoinTableOptions|JoinTableMuplipleColumnsOptions;
options = options || {} as JoinTableOptions|JoinTableMultipleColumnsOptions;
const args: JoinTableMetadataArgs = {
target: object.constructor,
propertyName: propertyName,
name: options.name,
joinColumns: (options && (options as JoinTableOptions).joinColumn ? [(options as JoinTableOptions).joinColumn!] : (options as JoinTableMuplipleColumnsOptions).joinColumns) as any,
inverseJoinColumns: (options && (options as JoinTableOptions).inverseJoinColumn ? [(options as JoinTableOptions).inverseJoinColumn!] : (options as JoinTableMuplipleColumnsOptions).inverseJoinColumns) as any,
joinColumns: (options && (options as JoinTableOptions).joinColumn ? [(options as JoinTableOptions).joinColumn!] : (options as JoinTableMultipleColumnsOptions).joinColumns) as any,
inverseJoinColumns: (options && (options as JoinTableOptions).inverseJoinColumn ? [(options as JoinTableOptions).inverseJoinColumn!] : (options as JoinTableMultipleColumnsOptions).inverseJoinColumns) as any,
};
getMetadataArgsStorage().joinTables.add(args);
};

View File

@ -4,7 +4,7 @@ import {OnDeleteType} from "../metadata/ForeignKeyMetadata";
import {JoinColumnOptions} from "../decorator/options/JoinColumnOptions";
import {ColumnType} from "../metadata/types/ColumnTypes";
import {RelationType} from "../metadata/types/RelationTypes";
import {JoinTableMuplipleColumnsOptions} from "../decorator/options/JoinTableMuplipleColumnsOptions";
import {JoinTableMultipleColumnsOptions} from "../decorator/options/JoinTableMuplipleColumnsOptions";
export interface EntitySchema {
@ -177,7 +177,7 @@ export interface EntitySchema {
/**
* Join table options of this column. If set to true then it simply means that it has a join table.
*/
joinTable?: boolean|JoinColumnOptions|JoinTableMuplipleColumnsOptions;
joinTable?: boolean|JoinColumnOptions|JoinTableMultipleColumnsOptions;
/**
* Join column options of this column. If set to true then it simply means that it has a join column.

View File

@ -50,7 +50,7 @@ export class LazyRelationsWrapper {
relation.joinColumns.forEach(joinColumn => {
qb.andWhere(`${relation.entityMetadata.name}.${joinColumn.referencedColumn.fullName} = :${joinColumn.referencedColumn.fullName}`)
.setParameter(`${joinColumn.referencedColumn.fullName}`, this[joinColumn.referencedColumn.fullName])
.setParameter(`${joinColumn.referencedColumn.fullName}`, this[joinColumn.referencedColumn.fullName]);
});
this[promiseIndex] = qb.getOne().then(result => {
@ -76,7 +76,7 @@ export class LazyRelationsWrapper {
relation.inverseRelation.joinColumns.forEach(joinColumn => {
qb.andWhere(`${relation.propertyName}.${joinColumn.name} = :${joinColumn.referencedColumn.fullName}`)
.setParameter(`${joinColumn.referencedColumn.fullName}`, this[joinColumn.referencedColumn.fullName])
.setParameter(`${joinColumn.referencedColumn.fullName}`, this[joinColumn.referencedColumn.fullName]);
});
const result = relation.isOneToMany ? qb.getMany() : qb.getOne();

View File

@ -26,7 +26,7 @@ import {EmbeddedMetadataArgs} from "../metadata-args/EmbeddedMetadataArgs";
import {RelationIdMetadata} from "../metadata/RelationIdMetadata";
import {RelationCountMetadata} from "../metadata/RelationCountMetadata";
import {JoinTableOptions} from "../decorator/options/JoinTableOptions";
import {JoinTableMuplipleColumnsOptions} from "../decorator/options/JoinTableMuplipleColumnsOptions";
import {JoinTableMultipleColumnsOptions} from "../decorator/options/JoinTableMuplipleColumnsOptions";
/**
* Aggregates all metadata: table, column, relation into one collection grouped by tables for a given set of classes.
@ -159,8 +159,8 @@ export class EntityMetadataBuilder {
target: schema.target || schema.name,
propertyName: relationName,
name: relationSchema.joinTable.name,
joinColumns: ((relationSchema.joinTable as JoinTableOptions).joinColumn ? [(relationSchema.joinTable as JoinTableOptions).joinColumn!] : (relationSchema.joinTable as JoinTableMuplipleColumnsOptions).joinColumns) as any,
inverseJoinColumns: ((relationSchema.joinTable as JoinTableOptions).inverseJoinColumn ? [(relationSchema.joinTable as JoinTableOptions).inverseJoinColumn!] : (relationSchema.joinTable as JoinTableMuplipleColumnsOptions).inverseJoinColumns) as any,
joinColumns: ((relationSchema.joinTable as JoinTableOptions).joinColumn ? [(relationSchema.joinTable as JoinTableOptions).joinColumn!] : (relationSchema.joinTable as JoinTableMultipleColumnsOptions).joinColumns) as any,
inverseJoinColumns: ((relationSchema.joinTable as JoinTableOptions).inverseJoinColumn ? [(relationSchema.joinTable as JoinTableOptions).inverseJoinColumn!] : (relationSchema.joinTable as JoinTableMultipleColumnsOptions).inverseJoinColumns) as any,
};
metadataArgsStorage.joinTables.add(joinTable);
}
@ -403,6 +403,7 @@ export class EntityMetadataBuilder {
// and create join column metadata args for them
const joinColumnArgsArray = mergedArgs.joinColumns.filterByProperty(relation.propertyName);
relation.joinColumns = reusable(
joinColumnArgsArray,
relation.inverseEntityMetadata.primaryColumnsWithParentIdColumns,
@ -411,7 +412,6 @@ export class EntityMetadataBuilder {
(columnName => namingStrategy.joinColumnName(relation.propertyName, columnName))
);
});
});
entityMetadatas.forEach(entityMetadata => {
@ -483,8 +483,7 @@ export class EntityMetadataBuilder {
// generate columns and foreign keys for tables with relations
entityMetadatas.forEach(metadata => {
metadata.relationsWithJoinColumns.forEach(relation => {
const columns = relation.joinColumns.map(joinColumn => {
relation.joinColumns.map(joinColumn => {
// find relational column and if it does not exist - add it
let relationalColumn = metadata.columns.find(column => column.fullName === joinColumn.name);
@ -503,8 +502,19 @@ export class EntityMetadataBuilder {
relationalColumn.relationMetadata = relation;
metadata.addColumn(relationalColumn);
}
return relationalColumn;
});
});
});
entityMetadatas.forEach(metadata => {
metadata.relationsWithJoinColumns.forEach(relation => {
const columns = relation.joinColumns.map(joinColumn => {
return metadata.columns.find(column => column.fullName === joinColumn.name)!;
});
// console.log("metadata:" , metadata.name);
// console.log("relation.relation:" , relation.propertyName);
// console.log("relation.joinColumns:" , relation.joinColumns);
// console.log("columns:" , columns);
// create and add foreign key
const inverseSideColumns = relation.joinColumns.map(joinColumn => joinColumn.referencedColumn);

View File

@ -76,8 +76,8 @@ export class SchemaBuilder {
await this.addNewColumns();
await this.updateExistColumns();
await this.updatePrimaryKeys();
await this.createIndices(); // we need to create indices before foreign keys because foreign keys rely on unique indices
await this.createForeignKeys();
await this.createIndices();
await this.queryRunner.commitTransaction();
} catch (error) {
@ -364,8 +364,6 @@ export class SchemaBuilder {
if (!tableSchema)
return;
// console.log(allIndexMetadatas);
// find depend indices to drop them
const dependIndices = allIndexMetadatas.filter(indexMetadata => {
return indexMetadata.tableName === tableName && indexMetadata.columns.indexOf(columnName) !== -1;

View File

@ -1,13 +0,0 @@
import {Entity} from "../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
@Entity()
export class Category {
@PrimaryColumn()
name: string;
@PrimaryColumn()
type: string;
}

View File

@ -1,28 +0,0 @@
import {Entity} from "../../../../../src/decorator/entity/Entity";
import {Column} from "../../../../../src/decorator/columns/Column";
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {ManyToOne} from "../../../../../src/decorator/relations/ManyToOne";
import {Category} from "./Category";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(type => Category)
// @JoinColumn([
// { name: "category_type", referencedColumnName: "type" },
// { name: "category_name", referencedColumnName: "name" }
// ])
category: Category;
// todo: test relation with multiple + empty join column one-to-one
// todo: test relation with multiple + empty join column many-to-one
// todo: test relation with multiple + single join column
// todo: test relation with multiple + multiple join columns
}

View File

@ -0,0 +1,46 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {Index} from "../../../../../../src/decorator/Index";
import {Post} from "./Post";
import {ManyToMany} from "../../../../../../src/decorator/relations/ManyToMany";
import {Tag} from "./Tag";
@Entity()
@Index(["code", "version", "description"], { unique: true })
export class Category {
@PrimaryColumn()
name: string;
@PrimaryColumn()
type: string;
@Column()
code: number;
@Column()
version: number;
@Column({nullable: true})
description: string;
@ManyToMany(type => Post, post => post.categories)
posts: Post[];
@ManyToMany(type => Post, post => post.categoriesWithOptions)
postsWithOptions: Post[];
@ManyToMany(type => Post, post => post.categoriesWithNonPrimaryColumns)
postsWithNonPrimaryColumns: Post[];
@ManyToMany(type => Tag, tag => tag.categories)
tags: Tag[];
@ManyToMany(type => Tag, tag => tag.categoriesWithOptions)
tagsWithOptions: Tag[];
@ManyToMany(type => Tag, tag => tag.categoriesWithNonPrimaryColumns)
tagsWithNonPrimaryColumns: Tag[];
}

View File

@ -0,0 +1,58 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {ManyToMany} from "../../../../../../src/decorator/relations/ManyToMany";
import {JoinTable} from "../../../../../../src/decorator/relations/JoinTable";
import {Category} from "./Category";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToMany(type => Category, category => category.posts)
@JoinTable()
categories: Category[];
@ManyToMany(type => Category, category => category.postsWithOptions)
@JoinTable({
name: "post_categories",
joinColumns: [{
name: "postId",
referencedColumnName: "id"
}],
inverseJoinColumns: [{
name: "categoryName",
referencedColumnName: "name"
}, {
name: "categoryType",
referencedColumnName: "type"
}]
})
categoriesWithOptions: Category[];
@ManyToMany(type => Category, category => category.postsWithNonPrimaryColumns)
@JoinTable({
name: "post_categories_non_primary",
joinColumns: [{
name: "postId",
referencedColumnName: "id"
}],
inverseJoinColumns: [{
name: "categoryCode",
referencedColumnName: "code"
}, {
name: "categoryVersion",
referencedColumnName: "version"
}, {
name: "categoryDescription",
referencedColumnName: "description"
}]
})
categoriesWithNonPrimaryColumns: Category[];
}

View File

@ -0,0 +1,67 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {ManyToMany} from "../../../../../../src/decorator/relations/ManyToMany";
import {JoinTable} from "../../../../../../src/decorator/relations/JoinTable";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Category} from "./Category";
import {Column} from "../../../../../../src/decorator/columns/Column";
@Entity()
export class Tag {
@Column()
code: number;
@PrimaryColumn()
title: string;
@PrimaryColumn()
description: string;
@ManyToMany(type => Category, category => category.tags)
@JoinTable()
categories: Category[];
@ManyToMany(type => Category, category => category.tagsWithOptions)
@JoinTable({
name: "tag_categories",
joinColumns: [{
name: "tagTitle",
referencedColumnName: "title"
}, {
name: "tagDescription",
referencedColumnName: "description"
}],
inverseJoinColumns: [{
name: "categoryName",
referencedColumnName: "name"
}, {
name: "categoryType",
referencedColumnName: "type"
}]
})
categoriesWithOptions: Category[];
@ManyToMany(type => Category, category => category.tagsWithNonPrimaryColumns)
@JoinTable({
name: "tag_categories_non_primary",
joinColumns: [{
name: "tagTitle",
referencedColumnName: "title"
}, {
name: "tagDescription",
referencedColumnName: "description"
}],
inverseJoinColumns: [{
name: "categoryCode",
referencedColumnName: "code"
}, {
name: "categoryVersion",
referencedColumnName: "version"
}, {
name: "categoryDescription",
referencedColumnName: "description"
}]
})
categoriesWithNonPrimaryColumns: Category[];
}

View File

@ -0,0 +1,784 @@
import "reflect-metadata";
import * as chai from "chai";
import {expect} from "chai";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
import {Connection} from "../../../../../src/connection/Connection";
import {Post} from "./entity/Post";
import {Category} from "./entity/Category";
import {Tag} from "./entity/Tag";
const should = chai.should();
describe("relations > multiple-primary-keys > many-to-many", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
describe("owning side", () => {
it("should load related entity when JoinTable used without options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
await connection.entityManager.persist(category3);
const post1 = new Post();
post1.title = "About BMW";
post1.categories = [category1, category2];
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categories = [category3];
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categories", "categories")
.orderBy("post.id, categories.code")
.getMany();
expect(loadedPosts[0].categories).to.not.be.empty;
expect(loadedPosts[0].categories[0].name).to.be.equal("cars");
expect(loadedPosts[0].categories[0].type).to.be.equal("common-category");
expect(loadedPosts[0].categories[1].name).to.be.equal("BMW");
expect(loadedPosts[0].categories[1].type).to.be.equal("cars-category");
expect(loadedPosts[1].categories).to.not.be.empty;
expect(loadedPosts[1].categories[0].name).to.be.equal("airplanes");
expect(loadedPosts[1].categories[0].type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categories", "categories")
.orderBy("categories.code")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.categories).to.not.be.empty;
expect(loadedPost!.categories[0].name).to.be.equal("cars");
expect(loadedPost!.categories[0].type).to.be.equal("common-category");
})));
it("should load related entity when JoinTable used with options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
await connection.entityManager.persist(category3);
const post1 = new Post();
post1.title = "About BMW";
post1.categoriesWithOptions = [category1, category2];
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoriesWithOptions = [category3];
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoriesWithOptions", "categories")
.orderBy("post.id, categories.code")
.getMany();
expect(loadedPosts[0].categoriesWithOptions).to.not.be.empty;
expect(loadedPosts[0].categoriesWithOptions[0].name).to.be.equal("cars");
expect(loadedPosts[0].categoriesWithOptions[0].type).to.be.equal("common-category");
expect(loadedPosts[0].categoriesWithOptions[1].name).to.be.equal("BMW");
expect(loadedPosts[0].categoriesWithOptions[1].type).to.be.equal("cars-category");
expect(loadedPosts[1].categoriesWithOptions).to.not.be.empty;
expect(loadedPosts[1].categoriesWithOptions[0].name).to.be.equal("airplanes");
expect(loadedPosts[1].categoriesWithOptions[0].type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoriesWithOptions", "categories")
.orderBy("categories.code")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.categoriesWithOptions).to.not.be.empty;
expect(loadedPost!.categoriesWithOptions[0].name).to.be.equal("cars");
expect(loadedPost!.categoriesWithOptions[0].type).to.be.equal("common-category");
})));
it("should load related entity when JoinTable references with non-primary columns", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of BMW";
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
category3.description = "category of airplanes";
await connection.entityManager.persist(category3);
const post1 = new Post();
post1.title = "About BMW";
post1.categoriesWithNonPrimaryColumns = [category1, category2];
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoriesWithNonPrimaryColumns = [category3];
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoriesWithNonPrimaryColumns", "categories")
.orderBy("post.id, categories.code")
.getMany();
expect(loadedPosts[0].categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[0].code).to.be.equal(1);
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of cars");
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[1].code).to.be.equal(2);
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[1].version).to.be.equal(1);
expect(loadedPosts[0].categoriesWithNonPrimaryColumns[1].description).to.be.equal("category of BMW");
expect(loadedPosts[1].categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[1].categoriesWithNonPrimaryColumns[0].code).to.be.equal(3);
expect(loadedPosts[1].categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedPosts[1].categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of airplanes");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoriesWithNonPrimaryColumns", "categories")
.orderBy("categories.code")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPost!.categoriesWithNonPrimaryColumns[0].code).to.be.equal(1);
expect(loadedPost!.categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedPost!.categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of cars");
})));
it("should load related entity when both entities have multiple primary columns and JoinTable used without options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
await connection.entityManager.persist(category3);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.categories = [category1, category2];
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
tag2.categories = [category3];
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categories", "categories")
.orderBy("tag.code, categories.code")
.getMany();
expect(loadedTags[0].categories).to.not.be.empty;
expect(loadedTags[0].categories[0].name).to.be.equal("cars");
expect(loadedTags[0].categories[0].type).to.be.equal("common-category");
expect(loadedTags[0].categories[1].name).to.be.equal("BMW");
expect(loadedTags[0].categories[1].type).to.be.equal("cars-category");
expect(loadedTags[1].categories).to.not.be.empty;
expect(loadedTags[1].categories[0].name).to.be.equal("airplanes");
expect(loadedTags[1].categories[0].type).to.be.equal("common-category");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categories", "categories")
.orderBy("categories.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.categories).to.not.be.empty;
expect(loadedTag!.categories[0].name).to.be.equal("cars");
expect(loadedTag!.categories[0].type).to.be.equal("common-category");
})));
it("should load related entity when both entities have multiple primary columns and JoinTable used with options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
await connection.entityManager.persist(category3);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.categoriesWithOptions = [category1, category2];
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Boeing";
tag2.description = "Tag about Boeing";
tag2.categoriesWithOptions = [category3];
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoriesWithOptions", "categories")
.orderBy("tag.code, categories.code")
.getMany();
expect(loadedTags[0].categoriesWithOptions).to.not.be.empty;
expect(loadedTags[0].categoriesWithOptions[0].name).to.be.equal("cars");
expect(loadedTags[0].categoriesWithOptions[0].type).to.be.equal("common-category");
expect(loadedTags[0].categoriesWithOptions[1].name).to.be.equal("BMW");
expect(loadedTags[0].categoriesWithOptions[1].type).to.be.equal("cars-category");
expect(loadedTags[1].categoriesWithOptions).to.not.be.empty;
expect(loadedTags[1].categoriesWithOptions[0].name).to.be.equal("airplanes");
expect(loadedTags[1].categoriesWithOptions[0].type).to.be.equal("common-category");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoriesWithOptions", "categories")
.orderBy("categories.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.categoriesWithOptions).to.not.be.empty;
expect(loadedTag!.categoriesWithOptions[0].name).to.be.equal("cars");
expect(loadedTag!.categoriesWithOptions[0].type).to.be.equal("common-category");
})));
it("should load related entity when both entities have multiple primary columns and JoinTable references with non-primary columns", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "BMW";
category2.type = "cars-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of BMW";
await connection.entityManager.persist(category2);
const category3 = new Category();
category3.name = "airplanes";
category3.type = "common-category";
category3.code = 3;
category3.version = 1;
category3.description = "category of airplanes";
await connection.entityManager.persist(category3);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.categoriesWithNonPrimaryColumns = [category1, category2];
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Boeing";
tag2.description = "Tag about Boeing";
tag2.categoriesWithNonPrimaryColumns = [category3];
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoriesWithNonPrimaryColumns", "categories")
.orderBy("tag.code, categories.code")
.getMany();
expect(loadedTags[0].categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTags[0].categoriesWithNonPrimaryColumns[0].code).to.be.equal(1);
expect(loadedTags[0].categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedTags[0].categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of cars");
expect(loadedTags[0].categoriesWithNonPrimaryColumns[1].code).to.be.equal(2);
expect(loadedTags[0].categoriesWithNonPrimaryColumns[1].version).to.be.equal(1);
expect(loadedTags[0].categoriesWithNonPrimaryColumns[1].description).to.be.equal("category of BMW");
expect(loadedTags[1].categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTags[1].categoriesWithNonPrimaryColumns[0].code).to.be.equal(3);
expect(loadedTags[1].categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedTags[1].categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of airplanes");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoriesWithNonPrimaryColumns", "categories")
.orderBy("categories.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.categoriesWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTag!.categoriesWithNonPrimaryColumns[0].code).to.be.equal(1);
expect(loadedTag!.categoriesWithNonPrimaryColumns[0].version).to.be.equal(1);
expect(loadedTag!.categoriesWithNonPrimaryColumns[0].description).to.be.equal("category of cars");
})));
});
describe("inverse side", () => {
it("should load related entity when JoinTable used without options", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.posts = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.posts = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.posts", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].posts).to.not.be.empty;
expect(loadedCategories[0].posts[0].id).to.be.equal(1);
expect(loadedCategories[0].posts[1].id).to.be.equal(2);
expect(loadedCategories[1].posts).to.not.be.empty;
expect(loadedCategories[1].posts[0].id).to.be.equal(3);
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.posts", "posts")
.orderBy("posts.id")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.posts).to.not.be.empty;
expect(loadedCategory!.posts[0].id).to.be.equal(1);
expect(loadedCategory!.posts[1].id).to.be.equal(2);
})));
it("should load related entity when JoinTable used with options", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.postsWithOptions = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.postsWithOptions = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithOptions", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].postsWithOptions).to.not.be.empty;
expect(loadedCategories[0].postsWithOptions[0].id).to.be.equal(1);
expect(loadedCategories[0].postsWithOptions[1].id).to.be.equal(2);
expect(loadedCategories[1].postsWithOptions).to.not.be.empty;
expect(loadedCategories[1].postsWithOptions[0].id).to.be.equal(3);
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithOptions", "posts")
.orderBy("posts.id")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.postsWithOptions).to.not.be.empty;
expect(loadedCategory!.postsWithOptions[0].id).to.be.equal(1);
expect(loadedCategory!.postsWithOptions[1].id).to.be.equal(2);
})));
it("should load related entity when JoinTable references with non-primary columns", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
category1.postsWithNonPrimaryColumns = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
category2.postsWithNonPrimaryColumns = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithNonPrimaryColumns", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[0].postsWithNonPrimaryColumns[0].id).to.be.equal(1);
expect(loadedCategories[0].postsWithNonPrimaryColumns[1].id).to.be.equal(2);
expect(loadedCategories[1].postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[1].postsWithNonPrimaryColumns[0].id).to.be.equal(3);
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithNonPrimaryColumns", "posts")
.orderBy("posts.id")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategory!.postsWithNonPrimaryColumns[0].id).to.be.equal(1);
expect(loadedCategory!.postsWithNonPrimaryColumns[1].id).to.be.equal(2);
})));
it("should load related entity when both entities have multiple primary columns and JoinTable used without options", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Audi";
tag2.description = "Tag about Audi";
await connection.entityManager.persist(tag2);
const tag3 = new Tag();
tag3.code = 3;
tag3.title = "About Boeing";
tag3.description = "tag about Boeing";
await connection.entityManager.persist(tag3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.tags = [tag1, tag2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.tags = [tag3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tags", "tags")
.orderBy("category.code, tags.code")
.getMany();
expect(loadedCategories[0].tags).to.not.be.empty;
expect(loadedCategories[0].tags[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].tags[0].description).to.be.equal("Tag about BMW");
expect(loadedCategories[0].tags[1].title).to.be.equal("About Audi");
expect(loadedCategories[0].tags[1].description).to.be.equal("Tag about Audi");
expect(loadedCategories[1].tags).to.not.be.empty;
expect(loadedCategories[1].tags[0].title).to.be.equal("About Boeing");
expect(loadedCategories[1].tags[0].description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tags", "tags")
.orderBy("tags.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tags).to.not.be.empty;
expect(loadedCategory!.tags[0].title).to.be.equal("About BMW");
expect(loadedCategory!.tags[0].description).to.be.equal("Tag about BMW");
})));
it("should load related entity when both entities have multiple primary columns and JoinTable used with options", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Audi";
tag2.description = "Tag about Audi";
await connection.entityManager.persist(tag2);
const tag3 = new Tag();
tag3.code = 3;
tag3.title = "About Boeing";
tag3.description = "tag about Boeing";
await connection.entityManager.persist(tag3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.tagsWithOptions = [tag1, tag2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.tagsWithOptions = [tag3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagsWithOptions", "tags")
.orderBy("category.code, tags.code")
.getMany();
expect(loadedCategories[0].tagsWithOptions).to.not.be.empty;
expect(loadedCategories[0].tagsWithOptions[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].tagsWithOptions[0].description).to.be.equal("Tag about BMW");
expect(loadedCategories[0].tagsWithOptions[1].title).to.be.equal("About Audi");
expect(loadedCategories[0].tagsWithOptions[1].description).to.be.equal("Tag about Audi");
expect(loadedCategories[1].tagsWithOptions).to.not.be.empty;
expect(loadedCategories[1].tagsWithOptions[0].title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagsWithOptions[0].description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagsWithOptions", "tags")
.orderBy("tags.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagsWithOptions).to.not.be.empty;
expect(loadedCategory!.tagsWithOptions[0].title).to.be.equal("About BMW");
expect(loadedCategory!.tagsWithOptions[0].description).to.be.equal("Tag about BMW");
})));
it("should load related entity when both entities have multiple primary columns and JoinTable references with non-primary columns", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 2;
tag2.title = "About Audi";
tag2.description = "Tag about Audi";
await connection.entityManager.persist(tag2);
const tag3 = new Tag();
tag3.code = 3;
tag3.title = "About Boeing";
tag3.description = "tag about Boeing";
await connection.entityManager.persist(tag3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
category1.tagsWithNonPrimaryColumns = [tag1, tag2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
category2.tagsWithNonPrimaryColumns = [tag3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagsWithNonPrimaryColumns", "tags")
.orderBy("category.code, tags.code")
.getMany();
expect(loadedCategories[0].tagsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[0].tagsWithNonPrimaryColumns[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].tagsWithNonPrimaryColumns[0].description).to.be.equal("Tag about BMW");
expect(loadedCategories[0].tagsWithNonPrimaryColumns[1].title).to.be.equal("About Audi");
expect(loadedCategories[0].tagsWithNonPrimaryColumns[1].description).to.be.equal("Tag about Audi");
expect(loadedCategories[1].tagsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[1].tagsWithNonPrimaryColumns[0].title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagsWithNonPrimaryColumns[0].description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagsWithNonPrimaryColumns", "tags")
.orderBy("tags.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategory!.tagsWithNonPrimaryColumns[0].title).to.be.equal("About BMW");
expect(loadedCategory!.tagsWithNonPrimaryColumns[0].description).to.be.equal("Tag about BMW");
})));
});
});

View File

@ -0,0 +1,39 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {Index} from "../../../../../../src/decorator/Index";
import {OneToMany} from "../../../../../../src/decorator/relations/OneToMany";
import {Post} from "./Post";
@Entity()
@Index(["code", "version", "description"], { unique: true })
export class Category {
@PrimaryColumn()
name: string;
@PrimaryColumn()
type: string;
@Column()
code: number;
@Column()
version: number;
@Column({nullable: true})
description: string;
@OneToMany(type => Post, post => post.category)
posts: Post[];
@OneToMany(type => Post, post => post.categoryWithEmptyJoinColumn)
postsWithEmptyJoinColumn: Post[];
@OneToMany(type => Post, post => post.categoryWithOptions)
postsWithOptions: Post[];
@OneToMany(type => Post, post => post.categoryWithNonPrimaryColumns)
postsWithNonPrimaryColumns: Post[];
}

View File

@ -0,0 +1,39 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {ManyToOne} from "../../../../../../src/decorator/relations/ManyToOne";
import {JoinColumn} from "../../../../../../src/decorator/relations/JoinColumn";
import {Category} from "./Category";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@ManyToOne(type => Category)
category: Category;
@ManyToOne(type => Category)
@JoinColumn()
categoryWithEmptyJoinColumn: Category;
@ManyToOne(type => Category)
@JoinColumn([
{ name: "category_name", referencedColumnName: "name" },
{ name: "category_type", referencedColumnName: "type" }
])
categoryWithOptions: Category;
@ManyToOne(type => Category)
@JoinColumn([
{ name: "category_code", referencedColumnName: "code" },
{ name: "category_version", referencedColumnName: "version" },
{ name: "category_description", referencedColumnName: "description" }
])
categoryWithNonPrimaryColumns: Category;
}

View File

@ -0,0 +1,479 @@
import "reflect-metadata";
import * as chai from "chai";
import {expect} from "chai";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
import {Connection} from "../../../../../src/connection/Connection";
import {Post} from "./entity/Post";
import {Category} from "./entity/Category";
const should = chai.should();
describe("relations > multiple-primary-keys > many-to-one", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
describe("owning side", () => {
it("should load related entity when JoinColumn is not specified", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About BMW";
post1.category = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.category = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].category).to.not.be.empty;
expect(loadedPosts[0].category.name).to.be.equal("cars");
expect(loadedPosts[0].category.type).to.be.equal("common-category");
expect(loadedPosts[1].category).to.not.be.empty;
expect(loadedPosts[1].category.name).to.be.equal("airplanes");
expect(loadedPosts[1].category.type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.where("post.id = :id", {id: 1})
.getOne();
expect(loadedPost!.category).to.not.be.empty;
expect(loadedPost!.category.name).to.be.equal("cars");
expect(loadedPost!.category.type).to.be.equal("common-category");
})));
it("should load related entity when JoinColumn is specified without options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About BMW";
post1.categoryWithEmptyJoinColumn = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoryWithEmptyJoinColumn = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithEmptyJoinColumn", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].categoryWithEmptyJoinColumn).to.not.be.empty;
expect(loadedPosts[0].categoryWithEmptyJoinColumn.name).to.be.equal("cars");
expect(loadedPosts[0].categoryWithEmptyJoinColumn.type).to.be.equal("common-category");
expect(loadedPosts[1].categoryWithEmptyJoinColumn).to.not.be.empty;
expect(loadedPosts[1].categoryWithEmptyJoinColumn.name).to.be.equal("airplanes");
expect(loadedPosts[1].categoryWithEmptyJoinColumn.type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithEmptyJoinColumn", "category")
.where("post.id = :id", {id: 1})
.getOne();
expect(loadedPost!.categoryWithEmptyJoinColumn).to.not.be.empty;
expect(loadedPost!.categoryWithEmptyJoinColumn.name).to.be.equal("cars");
expect(loadedPost!.categoryWithEmptyJoinColumn.type).to.be.equal("common-category");
})));
it("should load related entity when JoinColumn is specified with options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About BMW";
post1.categoryWithOptions = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoryWithOptions = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithOptions", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].categoryWithOptions).to.not.be.empty;
expect(loadedPosts[0].categoryWithOptions.name).to.be.equal("cars");
expect(loadedPosts[0].categoryWithOptions.type).to.be.equal("common-category");
expect(loadedPosts[1].categoryWithOptions).to.not.be.empty;
expect(loadedPosts[1].categoryWithOptions.name).to.be.equal("airplanes");
expect(loadedPosts[1].categoryWithOptions.type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithOptions", "category")
.where("post.id = :id", {id: 1})
.getOne();
expect(loadedPost!.categoryWithOptions).to.not.be.empty;
expect(loadedPost!.categoryWithOptions.name).to.be.equal("cars");
expect(loadedPost!.categoryWithOptions.type).to.be.equal("common-category");
})));
it("should load related entity when JoinColumn references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category about cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category about airplanes";
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About BMW";
post1.categoryWithNonPrimaryColumns = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoryWithNonPrimaryColumns = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithNonPrimaryColumns", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[0].categoryWithNonPrimaryColumns.code).to.be.equal(1);
expect(loadedPosts[0].categoryWithNonPrimaryColumns.version).to.be.equal(1);
expect(loadedPosts[0].categoryWithNonPrimaryColumns.description).to.be.equal("category about cars");
expect(loadedPosts[1].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[1].categoryWithNonPrimaryColumns.code).to.be.equal(2);
expect(loadedPosts[1].categoryWithNonPrimaryColumns.version).to.be.equal(1);
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithNonPrimaryColumns", "category")
.where("post.id = :id", {id: 1})
.getOne();
expect(loadedPost!.categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPost!.categoryWithNonPrimaryColumns.code).to.be.equal(1);
expect(loadedPost!.categoryWithNonPrimaryColumns.version).to.be.equal(1);
expect(loadedPost!.categoryWithNonPrimaryColumns.description).to.be.equal("category about cars");
})));
});
describe("inverse side", () => {
it("should load related entity when JoinColumn is not specified", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.posts = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.posts = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.posts", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].posts).to.not.be.empty;
expect(loadedCategories[0].posts[0].id).to.be.equal(1);
expect(loadedCategories[0].posts[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].posts[1].id).to.be.equal(2);
expect(loadedCategories[0].posts[1].title).to.be.equal("About Audi");
expect(loadedCategories[1].posts).to.not.be.empty;
expect(loadedCategories[1].posts[0].id).to.be.equal(3);
expect(loadedCategories[1].posts[0].title).to.be.equal("About Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.posts", "posts")
.orderBy("posts.id")
.where("category.code = :code", {code: 1})
.getOne();
expect(loadedCategory!.posts).to.not.be.empty;
expect(loadedCategory!.posts[0].id).to.be.equal(1);
expect(loadedCategory!.posts[0].title).to.be.equal("About BMW");
expect(loadedCategory!.posts[1].id).to.be.equal(2);
expect(loadedCategory!.posts[1].title).to.be.equal("About Audi");
})));
it("should load related entity when JoinColumn is specified without options", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.postsWithEmptyJoinColumn = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.postsWithEmptyJoinColumn = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithEmptyJoinColumn", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].postsWithEmptyJoinColumn).to.not.be.empty;
expect(loadedCategories[0].postsWithEmptyJoinColumn[0].id).to.be.equal(1);
expect(loadedCategories[0].postsWithEmptyJoinColumn[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].postsWithEmptyJoinColumn[1].id).to.be.equal(2);
expect(loadedCategories[0].postsWithEmptyJoinColumn[1].title).to.be.equal("About Audi");
expect(loadedCategories[1].postsWithEmptyJoinColumn).to.not.be.empty;
expect(loadedCategories[1].postsWithEmptyJoinColumn[0].id).to.be.equal(3);
expect(loadedCategories[1].postsWithEmptyJoinColumn[0].title).to.be.equal("About Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithEmptyJoinColumn", "posts")
.orderBy("posts.id")
.where("category.code = :code", {code: 1})
.getOne();
expect(loadedCategory!.postsWithEmptyJoinColumn).to.not.be.empty;
expect(loadedCategory!.postsWithEmptyJoinColumn[0].id).to.be.equal(1);
expect(loadedCategory!.postsWithEmptyJoinColumn[0].title).to.be.equal("About BMW");
expect(loadedCategory!.postsWithEmptyJoinColumn[1].id).to.be.equal(2);
expect(loadedCategory!.postsWithEmptyJoinColumn[1].title).to.be.equal("About Audi");
})));
it("should load related entity when JoinColumn is specified with options", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.postsWithOptions = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.postsWithOptions = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithOptions", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].postsWithOptions).to.not.be.empty;
expect(loadedCategories[0].postsWithOptions[0].id).to.be.equal(1);
expect(loadedCategories[0].postsWithOptions[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].postsWithOptions[1].id).to.be.equal(2);
expect(loadedCategories[0].postsWithOptions[1].title).to.be.equal("About Audi");
expect(loadedCategories[1].postsWithOptions).to.not.be.empty;
expect(loadedCategories[1].postsWithOptions[0].id).to.be.equal(3);
expect(loadedCategories[1].postsWithOptions[0].title).to.be.equal("About Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithOptions", "posts")
.orderBy("posts.id")
.where("category.code = :code", {code: 1})
.getOne();
expect(loadedCategory!.postsWithOptions).to.not.be.empty;
expect(loadedCategory!.postsWithOptions[0].id).to.be.equal(1);
expect(loadedCategory!.postsWithOptions[0].title).to.be.equal("About BMW");
expect(loadedCategory!.postsWithOptions[1].id).to.be.equal(2);
expect(loadedCategory!.postsWithOptions[1].title).to.be.equal("About Audi");
})));
it("should load related entity when JoinColumn references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Audi";
await connection.entityManager.persist(post2);
const post3 = new Post();
post3.title = "About Boeing";
await connection.entityManager.persist(post3);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
category1.postsWithNonPrimaryColumns = [post1, post2];
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
category2.postsWithNonPrimaryColumns = [post3];
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithNonPrimaryColumns", "posts")
.orderBy("category.code, posts.id")
.getMany();
expect(loadedCategories[0].postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[0].postsWithNonPrimaryColumns[0].id).to.be.equal(1);
expect(loadedCategories[0].postsWithNonPrimaryColumns[0].title).to.be.equal("About BMW");
expect(loadedCategories[0].postsWithNonPrimaryColumns[1].id).to.be.equal(2);
expect(loadedCategories[0].postsWithNonPrimaryColumns[1].title).to.be.equal("About Audi");
expect(loadedCategories[1].postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[1].postsWithNonPrimaryColumns[0].id).to.be.equal(3);
expect(loadedCategories[1].postsWithNonPrimaryColumns[0].title).to.be.equal("About Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.postsWithNonPrimaryColumns", "posts")
.orderBy("posts.id")
.where("category.code = :code", {code: 1})
.getOne();
expect(loadedCategory!.postsWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategory!.postsWithNonPrimaryColumns[0].id).to.be.equal(1);
expect(loadedCategory!.postsWithNonPrimaryColumns[0].title).to.be.equal("About BMW");
expect(loadedCategory!.postsWithNonPrimaryColumns[1].id).to.be.equal(2);
expect(loadedCategory!.postsWithNonPrimaryColumns[1].title).to.be.equal("About Audi");
})));
});
});

View File

@ -0,0 +1,46 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {Index} from "../../../../../../src/decorator/Index";
import {OneToOne} from "../../../../../../src/decorator/relations/OneToOne";
import {Post} from "./Post";
import {Tag} from "./Tag";
@Entity()
@Index(["code", "version", "description"], { unique: true })
export class Category {
@PrimaryColumn()
name: string;
@PrimaryColumn()
type: string;
@Column()
code: number;
@Column()
version: number;
@Column({nullable: true})
description: string;
@OneToOne(type => Post, post => post.category)
post: Post;
@OneToOne(type => Post, post => post.categoryWithOptions)
postWithOptions: Post;
@OneToOne(type => Post, post => post.categoryWithNonPrimaryColumns)
postWithNonPrimaryColumns: Post;
@OneToOne(type => Tag, tag => tag.category)
tag: Tag;
@OneToOne(type => Tag, tag => tag.categoryWithOptions)
tagWithOptions: Tag;
@OneToOne(type => Tag, tag => tag.categoryWithNonPrimaryColumns)
tagWithNonPrimaryColumns: Tag;
}

View File

@ -0,0 +1,36 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {JoinColumn} from "../../../../../../src/decorator/relations/JoinColumn";
import {OneToOne} from "../../../../../../src/decorator/relations/OneToOne";
import {Category} from "./Category";
@Entity()
export class Post {
@PrimaryGeneratedColumn()
id: number;
@Column()
title: string;
@OneToOne(type => Category, category => category.post)
@JoinColumn()
category: Category;
@OneToOne(type => Category, category => category.postWithOptions)
@JoinColumn([
{ name: "category_name", referencedColumnName: "name" },
{ name: "category_type", referencedColumnName: "type" }
])
categoryWithOptions: Category;
@OneToOne(type => Category, category => category.postWithNonPrimaryColumns)
@JoinColumn([
{ name: "category_code", referencedColumnName: "code" },
{ name: "category_version", referencedColumnName: "version" },
{ name: "category_description", referencedColumnName: "description" }
])
categoryWithNonPrimaryColumns: Category;
}

View File

@ -0,0 +1,39 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryColumn} from "../../../../../../src/decorator/columns/PrimaryColumn";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {OneToOne} from "../../../../../../src/decorator/relations/OneToOne";
import {JoinColumn} from "../../../../../../src/decorator/relations/JoinColumn";
import {Category} from "./Category";
@Entity()
export class Tag {
@Column()
code: number;
@PrimaryColumn()
title: string;
@PrimaryColumn()
description: string;
@OneToOne(type => Category, category => category.tag)
@JoinColumn()
category: Category;
@OneToOne(type => Category, category => category.tagWithOptions)
@JoinColumn([
{ name: "category_name", referencedColumnName: "name" },
{ name: "category_type", referencedColumnName: "type" }
])
categoryWithOptions: Category;
@OneToOne(type => Category, category => category.tagWithNonPrimaryColumns)
@JoinColumn([
{ name: "category_code", referencedColumnName: "code" },
{ name: "category_version", referencedColumnName: "version" },
{ name: "category_description", referencedColumnName: "description" }
])
categoryWithNonPrimaryColumns: Category;
}

View File

@ -0,0 +1,691 @@
import "reflect-metadata";
import * as chai from "chai";
import {expect} from "chai";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
import {Connection} from "../../../../../src/connection/Connection";
import {Category} from "./entity/Category";
import {Post} from "./entity/Post";
import {Tag} from "./entity/Tag";
const should = chai.should();
describe("relations > multiple-primary-keys > one-to-one", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
describe("owning side", () => {
it("should load related entity when JoinColumn is specified without options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About cars #1";
post1.category = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About cars #2";
post2.category = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].category).to.not.be.empty;
expect(loadedPosts[0].category.name).to.be.equal("cars");
expect(loadedPosts[0].category.type).to.be.equal("common-category");
expect(loadedPosts[1].category).to.not.be.empty;
expect(loadedPosts[1].category.name).to.be.equal("airplanes");
expect(loadedPosts[1].category.type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.where("post.id = :id", {id: 1})
.getOne();
expect(loadedPost!.category).to.not.be.empty;
expect(loadedPost!.category.name).to.be.equal("cars");
expect(loadedPost!.category.type).to.be.equal("common-category");
})));
it("should load related entity when JoinColumn is specified with options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About cars #1";
post1.categoryWithOptions = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About cars #2";
post2.categoryWithOptions = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithOptions", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].categoryWithOptions).to.not.be.empty;
expect(loadedPosts[0].categoryWithOptions.name).to.be.equal("cars");
expect(loadedPosts[0].categoryWithOptions.type).to.be.equal("common-category");
expect(loadedPosts[1].categoryWithOptions).to.not.be.empty;
expect(loadedPosts[1].categoryWithOptions.name).to.be.equal("airplanes");
expect(loadedPosts[1].categoryWithOptions.type).to.be.equal("common-category");
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithOptions", "category")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.categoryWithOptions).to.not.be.empty;
expect(loadedPost!.categoryWithOptions.name).to.be.equal("cars");
expect(loadedPost!.categoryWithOptions.type).to.be.equal("common-category");
})));
it("should load related entity when JoinColumn references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category about cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category about airplanes";
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About cars #1";
post1.categoryWithNonPrimaryColumns = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About cars #2";
post2.categoryWithNonPrimaryColumns = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithNonPrimaryColumns", "category")
.orderBy("post.id")
.getMany();
expect(loadedPosts[0].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[0].categoryWithNonPrimaryColumns.code).to.be.equal(1);
expect(loadedPosts[0].categoryWithNonPrimaryColumns.version).to.be.equal(1);
expect(loadedPosts[0].categoryWithNonPrimaryColumns.description).to.be.equal("category about cars");
expect(loadedPosts[1].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPosts[1].categoryWithNonPrimaryColumns.code).to.be.equal(2);
expect(loadedPosts[1].categoryWithNonPrimaryColumns.version).to.be.equal(1);
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithNonPrimaryColumns", "category")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedPost!.categoryWithNonPrimaryColumns.code).to.be.equal(1);
expect(loadedPost!.categoryWithNonPrimaryColumns.version).to.be.equal(1);
expect(loadedPost!.categoryWithNonPrimaryColumns.description).to.be.equal("category about cars");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn defined without options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.category = category1;
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
tag2.category = category2;
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.category", "category")
.orderBy("tag.code, category.code")
.getMany();
expect(loadedTags[0].category).to.not.be.empty;
expect(loadedTags[0].category.name).to.be.equal("cars");
expect(loadedTags[0].category.type).to.be.equal("common-category");
expect(loadedTags[1].category).to.not.be.empty;
expect(loadedTags[1].category.name).to.be.equal("airplanes");
expect(loadedTags[1].category.type).to.be.equal("common-category");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.category", "category")
.orderBy("category.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.category).to.not.be.empty;
expect(loadedTag!.category.name).to.be.equal("cars");
expect(loadedTag!.category.type).to.be.equal("common-category");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn defined with options", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
await connection.entityManager.persist(category2);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.categoryWithOptions = category1;
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
tag2.categoryWithOptions = category2;
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoryWithOptions", "category")
.orderBy("tag.code, category.code")
.getMany();
expect(loadedTags[0].categoryWithOptions).to.not.be.empty;
expect(loadedTags[0].categoryWithOptions.name).to.be.equal("cars");
expect(loadedTags[0].categoryWithOptions.type).to.be.equal("common-category");
expect(loadedTags[1].categoryWithOptions).to.not.be.empty;
expect(loadedTags[1].categoryWithOptions.name).to.be.equal("airplanes");
expect(loadedTags[1].categoryWithOptions.type).to.be.equal("common-category");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoryWithOptions", "category")
.orderBy("category.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.categoryWithOptions).to.not.be.empty;
expect(loadedTag!.categoryWithOptions.name).to.be.equal("cars");
expect(loadedTag!.categoryWithOptions.type).to.be.equal("common-category");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
await connection.entityManager.persist(category2);
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
tag1.categoryWithNonPrimaryColumns = category1;
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
tag2.categoryWithNonPrimaryColumns = category2;
await connection.entityManager.persist(tag2);
const loadedTags = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoryWithNonPrimaryColumns", "category")
.orderBy("tag.code, category.code")
.getMany();
expect(loadedTags[0].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTags[0].categoryWithNonPrimaryColumns.name).to.be.equal("cars");
expect(loadedTags[0].categoryWithNonPrimaryColumns.type).to.be.equal("common-category");
expect(loadedTags[1].categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTags[1].categoryWithNonPrimaryColumns.name).to.be.equal("airplanes");
expect(loadedTags[1].categoryWithNonPrimaryColumns.type).to.be.equal("common-category");
const loadedTag = await connection.entityManager
.createQueryBuilder(Tag, "tag")
.leftJoinAndSelect("tag.categoryWithNonPrimaryColumns", "category")
.orderBy("category.code")
.where("tag.code = :code", { code: 1 })
.getOne();
expect(loadedTag!.categoryWithNonPrimaryColumns).to.not.be.empty;
expect(loadedTag!.categoryWithNonPrimaryColumns.name).to.be.equal("cars");
expect(loadedTag!.categoryWithNonPrimaryColumns.type).to.be.equal("common-category");
})));
});
describe("inverse side", () => {
it("should load related entity when JoinColumn is specified without options", () => Promise.all(connections.map(async connection => {
const post1 = new Post();
post1.title = "About BMW";
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
await connection.entityManager.persist(post2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.post = post1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.post = post2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.post", "post")
.orderBy("category.code, post.id")
.getMany();
expect(loadedCategories[0].post).to.not.be.empty;
expect(loadedCategories[0].post.id).to.be.equal(1);
expect(loadedCategories[1].post).to.not.be.empty;
expect(loadedCategories[1].post.id).to.be.equal(2);
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.post", "post")
.orderBy("post.id")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.post).to.not.be.empty;
expect(loadedCategory!.post.id).to.be.equal(1);
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn defined without options", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
await connection.entityManager.persist(tag2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.tag = tag1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.tag = tag2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tag", "tag")
.orderBy("category.code, tag.code")
.getMany();
expect(loadedCategories[0].tag).to.not.be.empty;
expect(loadedCategories[0].tag.title).to.be.equal("About BMW");
expect(loadedCategories[0].tag.description).to.be.equal("Tag about BMW");
expect(loadedCategories[1].tag).to.not.be.empty;
expect(loadedCategories[1].tag.title).to.be.equal("About Boeing");
expect(loadedCategories[1].tag.description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tag", "tag")
.orderBy("tag.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tag).to.not.be.empty;
expect(loadedCategory!.tag.title).to.be.equal("About BMW");
expect(loadedCategory!.tag.description).to.be.equal("Tag about BMW");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn defined with options", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
await connection.entityManager.persist(tag2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.tagWithOptions = tag1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.tagWithOptions = tag2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithOptions", "tag")
.orderBy("category.code, tag.code")
.getMany();
expect(loadedCategories[0].tagWithOptions).to.not.be.empty;
expect(loadedCategories[0].tagWithOptions.title).to.be.equal("About BMW");
expect(loadedCategories[0].tagWithOptions.description).to.be.equal("Tag about BMW");
expect(loadedCategories[1].tagWithOptions).to.not.be.empty;
expect(loadedCategories[1].tagWithOptions.title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagWithOptions.description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithOptions", "tag")
.orderBy("tag.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagWithOptions).to.not.be.empty;
expect(loadedCategory!.tagWithOptions.title).to.be.equal("About BMW");
expect(loadedCategory!.tagWithOptions.description).to.be.equal("Tag about BMW");
})));
it("should load related entity when JoinColumns references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
await connection.entityManager.persist(tag2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
category1.tagWithNonPrimaryColumns = tag1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
category2.tagWithNonPrimaryColumns = tag2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithNonPrimaryColumns", "tag")
.orderBy("category.code, tag.code")
.getMany();
expect(loadedCategories[0].tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[0].tagWithNonPrimaryColumns.title).to.be.equal("About BMW");
expect(loadedCategories[0].tagWithNonPrimaryColumns.description).to.be.equal("Tag about BMW");
expect(loadedCategories[1].tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[1].tagWithNonPrimaryColumns.title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagWithNonPrimaryColumns.description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithNonPrimaryColumns", "tag")
.orderBy("tag.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategory!.tagWithNonPrimaryColumns.title).to.be.equal("About BMW");
expect(loadedCategory!.tagWithNonPrimaryColumns.description).to.be.equal("Tag about BMW");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn defined with options", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
await connection.entityManager.persist(tag2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.tagWithOptions = tag1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.tagWithOptions = tag2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithOptions", "tag")
.orderBy("category.code, tag.code")
.getMany();
expect(loadedCategories[0].tagWithOptions).to.not.be.empty;
expect(loadedCategories[0].tagWithOptions.title).to.be.equal("About BMW");
expect(loadedCategories[0].tagWithOptions.description).to.be.equal("Tag about BMW");
expect(loadedCategories[1].tagWithOptions).to.not.be.empty;
expect(loadedCategories[1].tagWithOptions.title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagWithOptions.description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithOptions", "tag")
.orderBy("tag.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagWithOptions).to.not.be.empty;
expect(loadedCategory!.tagWithOptions.title).to.be.equal("About BMW");
expect(loadedCategory!.tagWithOptions.description).to.be.equal("Tag about BMW");
})));
it("should load related entity when both entities have multiple primary columns and JoinColumn references on to non-primary columns", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.code = 1;
tag1.title = "About BMW";
tag1.description = "Tag about BMW";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.code = 3;
tag2.title = "About Boeing";
tag2.description = "tag about Boeing";
await connection.entityManager.persist(tag2);
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
category1.code = 1;
category1.version = 1;
category1.description = "category of cars";
category1.tagWithNonPrimaryColumns = tag1;
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
category2.code = 2;
category2.version = 1;
category2.description = "category of airplanes";
category2.tagWithNonPrimaryColumns = tag2;
await connection.entityManager.persist(category2);
const loadedCategories = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithNonPrimaryColumns", "tag")
.orderBy("category.code, tag.code")
.getMany();
expect(loadedCategories[0].tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[0].tagWithNonPrimaryColumns.title).to.be.equal("About BMW");
expect(loadedCategories[0].tagWithNonPrimaryColumns.description).to.be.equal("Tag about BMW");
expect(loadedCategories[1].tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategories[1].tagWithNonPrimaryColumns.title).to.be.equal("About Boeing");
expect(loadedCategories[1].tagWithNonPrimaryColumns.description).to.be.equal("tag about Boeing");
const loadedCategory = await connection.entityManager
.createQueryBuilder(Category, "category")
.leftJoinAndSelect("category.tagWithNonPrimaryColumns", "tag")
.orderBy("tag.code")
.where("category.code = :code", { code: 1 })
.getOne();
expect(loadedCategory!.tagWithNonPrimaryColumns).to.not.be.empty;
expect(loadedCategory!.tagWithNonPrimaryColumns.title).to.be.equal("About BMW");
expect(loadedCategory!.tagWithNonPrimaryColumns.description).to.be.equal("Tag about BMW");
})));
});
});

View File

@ -0,0 +1,22 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {OneToMany} from "../../../../../../src/decorator/relations/OneToMany";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {EventMember} from "./EventMember";
@Entity()
export class Event {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
/* @ManyToOne(type => Person)
author: Person;*/
@OneToMany(type => EventMember, member => member.event)
members: EventMember[];
}

View File

@ -0,0 +1,15 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {ManyToOne} from "../../../../../../src/decorator/relations/ManyToOne";
import {Event} from "./Event";
import {User} from "./User";
@Entity()
export class EventMember {
@ManyToOne(type => Event, event => event.members, { primary: true })
event: Event;
@ManyToOne(type => User, user => user.members, { primary: true })
user: User;
}

View File

@ -0,0 +1,17 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {OneToOne} from "../../../../../../src/decorator/relations/OneToOne";
import {JoinColumn} from "../../../../../../src/decorator/relations/JoinColumn";
import {User} from "./User";
@Entity()
export class Person {
@Column()
fullName: string;
@OneToOne(type => User, { primary: true })
@JoinColumn()
user: User;
}

View File

@ -0,0 +1,19 @@
import {Entity} from "../../../../../../src/decorator/entity/Entity";
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
import {OneToMany} from "../../../../../../src/decorator/relations/OneToMany";
import {Column} from "../../../../../../src/decorator/columns/Column";
import {EventMember} from "./EventMember";
@Entity()
export class User {
@PrimaryGeneratedColumn()
id: number;
@Column()
name: string;
@OneToMany(type => EventMember, member => member.user)
members: EventMember[];
}

View File

@ -0,0 +1,104 @@
import "reflect-metadata";
import * as chai from "chai";
import {expect} from "chai";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
import {Connection} from "../../../../../src/connection/Connection";
import {User} from "./entity/User";
import {EventMember} from "./entity/EventMember";
import {Event} from "./entity/Event";
const should = chai.should();
describe("relations > multiple-primary-keys > other-cases", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
it("should load related entity when entity uses relation ids as primary id", () => Promise.all(connections.map(async connection => {
const user1 = new User();
user1.name = "Alice";
await connection.entityManager.persist(user1);
const user2 = new User();
user2.name = "Bob";
await connection.entityManager.persist(user2);
const user3 = new User();
user3.name = "Clara";
await connection.entityManager.persist(user3);
const event1 = new Event();
event1.name = "Event #1";
await connection.entityManager.persist(event1);
const event2 = new Event();
event2.name = "Event #2";
await connection.entityManager.persist(event2);
const eventMember1 = new EventMember();
eventMember1.user = user1;
eventMember1.event = event1;
await connection.entityManager.persist(eventMember1);
const eventMember2 = new EventMember();
eventMember2.user = user2;
eventMember2.event = event1;
await connection.entityManager.persist(eventMember2);
const eventMember3 = new EventMember();
eventMember3.user = user1;
eventMember3.event = event2;
await connection.entityManager.persist(eventMember3);
const eventMember4 = new EventMember();
eventMember4.user = user3;
eventMember4.event = event2;
await connection.entityManager.persist(eventMember4);
const loadedEvents = await connection.entityManager
.createQueryBuilder(Event, "event")
.leftJoinAndSelect("event.members", "members")
.leftJoinAndSelect("members.user", "user")
.orderBy("event.id, user.id")
.getMany();
expect(loadedEvents[0].members).to.not.be.empty;
expect(loadedEvents[0].members[0].user.id).to.be.equal(1);
expect(loadedEvents[0].members[0].user.name).to.be.equal("Alice");
expect(loadedEvents[0].members[1].user.id).to.be.equal(2);
expect(loadedEvents[0].members[1].user.name).to.be.equal("Bob");
expect(loadedEvents[1].members).to.not.be.empty;
expect(loadedEvents[1].members[0].user.id).to.be.equal(1);
expect(loadedEvents[1].members[0].user.name).to.be.equal("Alice");
expect(loadedEvents[1].members[1].user.id).to.be.equal(3);
expect(loadedEvents[1].members[1].user.name).to.be.equal("Clara");
const loadedUsers = await connection.entityManager
.createQueryBuilder(User, "user")
.leftJoinAndSelect("user.members", "members")
.leftJoinAndSelect("members.event", "event")
.orderBy("user.id, event.id")
.getMany();
expect(loadedUsers[0].members).to.not.be.empty;
expect(loadedUsers[0].members[0].event.id).to.be.equal(1);
expect(loadedUsers[0].members[0].event.name).to.be.equal("Event #1");
expect(loadedUsers[0].members[1].event.id).to.be.equal(2);
expect(loadedUsers[0].members[1].event.name).to.be.equal("Event #2");
expect(loadedUsers[1].members).to.not.be.empty;
expect(loadedUsers[1].members[0].event.id).to.be.equal(1);
expect(loadedUsers[1].members[0].event.name).to.be.equal("Event #1");
expect(loadedUsers[2].members).to.not.be.empty;
expect(loadedUsers[2].members[0].event.id).to.be.equal(2);
expect(loadedUsers[2].members[0].event.name).to.be.equal("Event #2");
})));
});

View File

@ -1,65 +0,0 @@
import "reflect-metadata";
import * as chai from "chai";
import {expect} from "chai";
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
import {Connection} from "../../../../src/connection/Connection";
import {Post} from "./entity/Post";
import {Category} from "./entity/Category";
const should = chai.should();
describe("relations > multiple-primary-keys", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
entities: [__dirname + "/entity/*{.js,.ts}"],
schemaCreate: true,
dropSchemaOnConnection: true,
}));
beforeEach(() => reloadTestingDatabases(connections));
after(() => closeTestingConnections(connections));
it("should load related entity when multiple primary keys used", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
category1.type = "common-category";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
category2.type = "common-category";
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About cars #1";
post1.category = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About cars #2";
post2.category = category2;
await connection.entityManager.persist(post2);
let loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.getMany();
expect(loadedPosts![0].category).to.not.be.empty;
expect(loadedPosts![0].category.type).to.be.equal("common-category");
expect(loadedPosts![1].category).to.not.be.empty;
expect(loadedPosts![1].category.type).to.be.equal("common-category");
let loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.category", "category")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.category).to.not.be.empty;
expect(loadedPost!.category.type).to.be.equal("common-category");
})));
});