more tests for join columns

This commit is contained in:
Zotov Dmitry 2017-04-21 15:30:29 +05:00
parent 59370008df
commit 84c7c93c50
4 changed files with 110 additions and 5 deletions

View File

@ -20,6 +20,7 @@ export interface JoinColumnMetadataArgs {
/**
* Name of the column in the entity to which this column is referenced.
* This is column property name, not a column database name.
*/
readonly referencedColumnName?: string;

View File

@ -340,13 +340,33 @@ export class EntityMetadataBuilder {
.concat(entityMetadata.manyToOneRelations)
.forEach(relation => {
// since for many-to-one relations having JoinColumn is not required on decorators level, we need to go
// throw all of them which don't have JoinColumn decorators and create it for them
// cases it should cover:
// 1. when join column is set with custom name and without referenced column name
// we need automatically set referenced column name - primary ids by default
// @JoinColumn({ name: "custom_name" })
// 2. when join column is set with only referenced column name
// we need automatically set join column name - relation name + referenced column name
// @JoinColumn({ referencedColumnName: "title" })
// 3. when join column is set without both referenced column name and join column name
// we need to automatically set both of them
// @JoinColumn()
// 4. when join column is not set at all (as in case of @ManyToOne relation)
// we need to create join column for it with proper referenced column name and join column name
// 5. when multiple join columns set none of referencedColumnName and name can be optional
// both options are required
// @JoinColumn([
// { name: "category_title", referencedColumnName: "type" },
// { name: "category_title", referencedColumnName: "name" },
// ])
// since for many-to-one relations having JoinColumn decorator is not required,
// we need to go thought each many-to-one relation without join column decorator set
// and create join column metadata args for them
let joinColumnMetadataArgsArray = mergedArgs.joinColumns.filterByProperty(relation.propertyName);
const hasAnyReferencedColumnName = joinColumnMetadataArgsArray.find(joinColumnArgs => !!joinColumnArgs.referencedColumnName);
if ((joinColumnMetadataArgsArray.length === 0 && relation.isManyToOne) ||
(joinColumnMetadataArgsArray.length > 0 && !hasAnyReferencedColumnName)) {
(joinColumnMetadataArgsArray.length > 0 && !hasAnyReferencedColumnName)) { // covers case3 and case1
joinColumnMetadataArgsArray = relation.inverseEntityMetadata.primaryColumnsWithParentIdColumns.map(primaryColumn => {
@ -367,7 +387,7 @@ export class EntityMetadataBuilder {
joinColumn.target = joinColumnMetadataArgs.target;
joinColumn.propertyName = joinColumnMetadataArgs.propertyName;
const referencedColumn = relation.inverseEntityMetadata.allColumns.find(column => {
return column.propertyName === joinColumnMetadataArgs!.referencedColumnName; // todo: FULLNAME OR PROPERTY NAME? (probably should be propertyName)
return column.propertyName === joinColumnMetadataArgs.referencedColumnName;
});
if (!referencedColumn)
throw new Error(`Referenced column ${joinColumnMetadataArgs.referencedColumnName} was not found in entity ${relation.inverseEntityMetadata.name}`);

View File

@ -9,7 +9,7 @@ import {Tag} from "./entity/Tag";
const should = chai.should();
describe("relations > custom-referenced-column-name", () => {
describe.only("relations > custom-referenced-column-name", () => {
let connections: Connection[];
before(async () => connections = await createTestingConnections({
@ -61,6 +61,44 @@ describe("relations > custom-referenced-column-name", () => {
})));
it("should load related entity when relation defined with empty join column", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
category1.name = "cars";
await connection.entityManager.persist(category1);
const category2 = new Category();
category2.name = "airplanes";
await connection.entityManager.persist(category2);
const post1 = new Post();
post1.title = "About BMW";
post1.categoryWithEmptyJoinCol = category1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.categoryWithEmptyJoinCol = category2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.categoryWithEmptyJoinCol", "categoryWithEmptyJoinCol")
.getMany();
expect(loadedPosts![0].categoryWithEmptyJoinCol.id).to.be.equal(1);
expect(loadedPosts![1].categoryWithEmptyJoinCol.id).to.be.equal(2);
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.where("post.id = :id", { id: 1 })
.leftJoinAndSelect("post.categoryWithEmptyJoinCol", "categoryWithEmptyJoinCol")
.getOne();
expect(loadedPost!.categoryWithEmptyJoinCol.id).to.be.equal(1);
})));
it("should load related entity when relation defined without reference column name", () => Promise.all(connections.map(async connection => {
const category1 = new Category();
@ -259,6 +297,44 @@ describe("relations > custom-referenced-column-name", () => {
})));
it("should load related entity when relation defined without column name", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();
tag1.name = "tag #1";
await connection.entityManager.persist(tag1);
const tag2 = new Tag();
tag2.name = "tag #2";
await connection.entityManager.persist(tag2);
const post1 = new Post();
post1.title = "About BMW";
post1.tagWithEmptyJoinCol = tag1;
await connection.entityManager.persist(post1);
const post2 = new Post();
post2.title = "About Boeing";
post2.tagWithEmptyJoinCol = tag2;
await connection.entityManager.persist(post2);
const loadedPosts = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.tagWithEmptyJoinCol", "tagWithEmptyJoinCol")
.getMany();
expect(loadedPosts![0].tagWithEmptyJoinCol.id).to.be.equal(1);
expect(loadedPosts![1].tagWithEmptyJoinCol.id).to.be.equal(2);
const loadedPost = await connection.entityManager
.createQueryBuilder(Post, "post")
.leftJoinAndSelect("post.tagWithEmptyJoinCol", "tagWithEmptyJoinCol")
.where("post.id = :id", { id: 1 })
.getOne();
expect(loadedPost!.tagWithEmptyJoinCol.id).to.be.equal(1);
})));
it("should load related entity when relation defined without reference column name", () => Promise.all(connections.map(async connection => {
const tag1 = new Tag();

View File

@ -28,6 +28,10 @@ export class Post {
@Column({ type: "int", nullable: true })
tagId: number;
@ManyToOne(type => Category)
@JoinColumn()
categoryWithEmptyJoinCol: Category;
@ManyToOne(type => Category)
@JoinColumn({ name: "categoryId" })
categoryWithoutRefColName: Category;
@ -44,6 +48,10 @@ export class Post {
@JoinColumn({ name: "categoryName", referencedColumnName: "name" })
category: Category;
@OneToOne(type => Tag)
@JoinColumn()
tagWithEmptyJoinCol: Tag;
@OneToOne(type => Tag)
@JoinColumn({ name: "tagId" })
tagWithoutRefColName: Tag;