mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
implementing multiple primary key functionality in to RelationId
This commit is contained in:
parent
e4c40d936d
commit
50d350434b
@ -11,6 +11,6 @@ export interface JoinColumnOptions {
|
||||
/**
|
||||
* Name of the column in the entity to which this column is referenced.
|
||||
*/
|
||||
readonly referencedColumnName?: string;
|
||||
readonly referencedColumnName?: string; // TODO rename to referencedColumn
|
||||
|
||||
}
|
||||
@ -239,16 +239,7 @@ export class ColumnMetadata {
|
||||
if (this.embeddedMetadata) {
|
||||
|
||||
// because embedded can be inside other embedded we need to go recursively and collect all prefix name
|
||||
const prefixes: string[] = [];
|
||||
const buildPrefixRecursively = (embeddedMetadata: EmbeddedMetadata) => {
|
||||
if (embeddedMetadata.parentEmbeddedMetadata)
|
||||
buildPrefixRecursively(embeddedMetadata.parentEmbeddedMetadata);
|
||||
|
||||
prefixes.push(embeddedMetadata.prefix);
|
||||
};
|
||||
buildPrefixRecursively(this.embeddedMetadata);
|
||||
|
||||
return this.entityMetadata.namingStrategy.embeddedColumnName(prefixes, this.propertyName, this._name);
|
||||
return this.entityMetadata.namingStrategy.embeddedColumnName(this.embeddedMetadata.prefix, this.propertyName, this._name);
|
||||
}
|
||||
|
||||
// if there is a naming strategy then use it to normalize propertyName as column name
|
||||
|
||||
@ -4,7 +4,6 @@ import {IndexMetadata} from "./IndexMetadata";
|
||||
import {RelationTypes} from "./types/RelationTypes";
|
||||
import {ForeignKeyMetadata} from "./ForeignKeyMetadata";
|
||||
import {NamingStrategyInterface} from "../naming-strategy/NamingStrategyInterface";
|
||||
import {EntityMetadataArgs} from "../metadata-args/EntityMetadataArgs";
|
||||
import {EmbeddedMetadata} from "./EmbeddedMetadata";
|
||||
import {ObjectLiteral} from "../common/ObjectLiteral";
|
||||
import {LazyRelationsWrapper} from "../lazy-loading/LazyRelationsWrapper";
|
||||
@ -209,7 +208,6 @@ export class EntityMetadata {
|
||||
|
||||
/**
|
||||
* Columns of the entity, including columns that are coming from the embeddeds of this entity.
|
||||
* @deprecated
|
||||
*/
|
||||
get columns(): ColumnMetadata[] {
|
||||
return this.embeddeds.reduce((columns, embedded) => columns.concat(embedded.columnsFromTree), this.ownColumns);
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
import {NamingStrategyInterface} from "./NamingStrategyInterface";
|
||||
import {RandomGenerator} from "../util/RandomGenerator";
|
||||
import {camelCase, snakeCase} from "../util/StringUtils";
|
||||
import {TableType} from "../metadata/types/TableTypes";
|
||||
|
||||
/**
|
||||
* Naming strategy that is used by default.
|
||||
@ -31,11 +30,9 @@ export class DefaultNamingStrategy implements NamingStrategyInterface {
|
||||
return customName ? customName : propertyName;
|
||||
}
|
||||
|
||||
embeddedColumnName(prefixes: string[], columnPropertyName: string, columnCustomName?: string): string {
|
||||
embeddedColumnName(prefix: string, columnPropertyName: string, columnCustomName?: string): string {
|
||||
// todo: need snake case property name but only if its a property name and not a custom embedded prefix
|
||||
prefixes = prefixes.filter(prefix => !!prefix);
|
||||
const embeddedPropertyName = prefixes.length ? prefixes.join("_") + "_" : "";
|
||||
return camelCase(embeddedPropertyName + (columnCustomName ? columnCustomName : columnPropertyName));
|
||||
return camelCase(prefix + "_" + (columnCustomName ? columnCustomName : columnPropertyName));
|
||||
}
|
||||
|
||||
relationName(propertyName: string): string {
|
||||
|
||||
@ -32,7 +32,7 @@ export interface NamingStrategyInterface {
|
||||
/**
|
||||
* Gets the embedded's column name from the given property name.
|
||||
*/
|
||||
embeddedColumnName(prefixes: string[], columnPropertyName: string, columnCustomName?: string): string;
|
||||
embeddedColumnName(prefix: string, columnPropertyName: string, columnCustomName?: string): string;
|
||||
|
||||
/**
|
||||
* Gets the table's relation name from the given property name.
|
||||
|
||||
@ -5,6 +5,7 @@ import {Subject} from "./Subject";
|
||||
import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider";
|
||||
import {SpecificRepository} from "../repository/SpecificRepository";
|
||||
import {MongoDriver} from "../driver/mongodb/MongoDriver";
|
||||
import {OrmUtils} from "../util/OrmUtils";
|
||||
|
||||
/**
|
||||
* To be able to execute persistence operations we need to load all entities from the database we need.
|
||||
@ -777,6 +778,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
|
||||
const specificRepository = new SpecificRepository(this.connection, subject.metadata, this.queryRunnerProvider);
|
||||
existInverseEntityRelationIds = await specificRepository
|
||||
.findRelationIds(relation, subject.databaseEntity);
|
||||
// console.log(existInverseEntityRelationIds);
|
||||
}
|
||||
|
||||
// get all inverse entities relation ids that are "bind" to the currently persisted entity
|
||||
@ -784,8 +786,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
|
||||
.map(subRelationValue => {
|
||||
const joinColumns = relation.isOwning ? relation.inverseJoinColumns : relation.inverseRelation.joinColumns;
|
||||
return joinColumns.reduce((ids, joinColumn) => {
|
||||
ids[joinColumn.referencedColumn!.propertyName] = subRelationValue[joinColumn.referencedColumn!.propertyName];
|
||||
return ids;
|
||||
return OrmUtils.mergeDeep(ids, joinColumn.createValueMap(joinColumn.referencedColumn!.getEntityValue(subRelationValue))); // todo: duplicate. relation.createJoinColumnsIdMap(entity) ?
|
||||
}, {} as ObjectLiteral);
|
||||
})
|
||||
.filter(subRelationValue => subRelationValue !== undefined && subRelationValue !== null);
|
||||
@ -804,8 +805,7 @@ export class SubjectBuilder<Entity extends ObjectLiteral> {
|
||||
|
||||
const joinColumns = relation.isOwning ? relation.inverseJoinColumns : relation.inverseRelation.joinColumns;
|
||||
const ids = joinColumns.reduce((ids, joinColumn) => {
|
||||
ids[joinColumn.referencedColumn!.propertyName] = subRelatedValue[joinColumn.referencedColumn!.propertyName];
|
||||
return ids;
|
||||
return OrmUtils.mergeDeep(ids, joinColumn.createValueMap(joinColumn.referencedColumn!.getEntityValue(subRelatedValue))); // todo: duplicate. relation.createJoinColumnsIdMap(entity) ?
|
||||
}, {} as ObjectLiteral);
|
||||
return !existInverseEntityRelationIds.find(relationId => {
|
||||
return relation.inverseEntityMetadata.compareIds(relationId, ids);
|
||||
|
||||
@ -8,7 +8,6 @@ import {QueryRunnerProvider} from "../query-runner/QueryRunnerProvider";
|
||||
import {EntityManager} from "../entity-manager/EntityManager";
|
||||
import {PromiseUtils} from "../util/PromiseUtils";
|
||||
import {MongoDriver} from "../driver/mongodb/MongoDriver";
|
||||
import {EmbeddedMetadata} from "../metadata/EmbeddedMetadata";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
|
||||
/**
|
||||
@ -318,6 +317,8 @@ export class SubjectOperationExecutor {
|
||||
if (!Object.keys(conditions).length)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
const updatePromise = this.queryRunner.update(subject.metadata.tableName, updateOptions, conditions);
|
||||
updatePromises.push(updatePromise);
|
||||
}
|
||||
|
||||
@ -37,8 +37,8 @@ export class RelationIdAttribute {
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private expressionMap: QueryExpressionMap,
|
||||
relationIdAttribute?: Partial<RelationIdAttribute>) {
|
||||
constructor(private queryExpressionMap: QueryExpressionMap,
|
||||
relationIdAttribute?: Partial<RelationIdAttribute>) {
|
||||
Object.assign(this, relationIdAttribute || {});
|
||||
}
|
||||
|
||||
@ -60,7 +60,7 @@ export class RelationIdAttribute {
|
||||
if (!QueryBuilderUtils.isAliasProperty(this.relationName))
|
||||
throw new Error(`Given value must be a string representation of alias property`);
|
||||
|
||||
return this.relationName.split(".")[0];
|
||||
return this.relationName.substr(0, this.relationName.indexOf("."));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -70,11 +70,11 @@ export class RelationIdAttribute {
|
||||
* This value is extracted from entityOrProperty value.
|
||||
* This is available when join was made using "post.category" syntax.
|
||||
*/
|
||||
get relationProperty(): string {
|
||||
get relationPropertyPath(): string {
|
||||
if (!QueryBuilderUtils.isAliasProperty(this.relationName))
|
||||
throw new Error(`Given value must be a string representation of alias property`);
|
||||
|
||||
return this.relationName.split(".")[1];
|
||||
return this.relationName.substr(this.relationName.indexOf(".") + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -86,9 +86,8 @@ export class RelationIdAttribute {
|
||||
if (!QueryBuilderUtils.isAliasProperty(this.relationName))
|
||||
throw new Error(`Given value must be a string representation of alias property`);
|
||||
|
||||
const [parentAlias, relationProperty] = this.relationName.split(".");
|
||||
const relationOwnerSelection = this.expressionMap.findAliasByName(parentAlias);
|
||||
return relationOwnerSelection.metadata.findRelationWithPropertyName(relationProperty);
|
||||
const relationOwnerSelection = this.queryExpressionMap.findAliasByName(this.parentAlias!);
|
||||
return relationOwnerSelection.metadata.findRelationWithPropertyPath(this.relationPropertyPath!);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -99,18 +98,6 @@ export class RelationIdAttribute {
|
||||
return parentAlias + "_" + relationProperty + "_relation_id";
|
||||
}
|
||||
|
||||
/*get referenceColumnName(): string {
|
||||
if (this.relation.isManyToOne || this.relation.isOneToOneOwner) {
|
||||
return this.relation.joinColumn.referencedColumn.fullName;
|
||||
|
||||
} else if (this.relation.isOneToMany || this.relation.isOneToOneNotOwner) {
|
||||
return this.relation.inverseRelation.joinColumn.referencedColumn.fullName;
|
||||
|
||||
} else {
|
||||
return this.relation.isOwning ? this.relation.joinTable.referencedColumn.fullName : this.relation.inverseRelation.joinTable.referencedColumn.fullName;
|
||||
}
|
||||
}*/
|
||||
|
||||
/**
|
||||
* Metadata of the joined entity.
|
||||
* If extra condition without entity was joined, then it will return undefined.
|
||||
@ -120,11 +107,11 @@ export class RelationIdAttribute {
|
||||
}
|
||||
|
||||
get mapToPropertyParentAlias(): string {
|
||||
return this.mapToProperty!.split(".")[0];
|
||||
return this.mapToProperty.substr(0, this.mapToProperty.indexOf("."));
|
||||
}
|
||||
|
||||
get mapToPropertyPropertyName(): string {
|
||||
return this.mapToProperty!.split(".")[1];
|
||||
get mapToPropertyPropertyPath(): string {
|
||||
return this.mapToProperty.substr(this.mapToProperty.indexOf(".") + 1);
|
||||
}
|
||||
|
||||
}
|
||||
@ -2,5 +2,5 @@ import {RelationIdAttribute} from "./RelationIdAttribute";
|
||||
|
||||
export interface RelationIdLoadResult {
|
||||
relationIdAttribute: RelationIdAttribute;
|
||||
results: { id: any, parentId: any, manyToManyId?: any }[];
|
||||
results: any[];
|
||||
}
|
||||
@ -47,85 +47,54 @@ export class RelationIdLoader {
|
||||
|
||||
} else if (relationIdAttr.relation.isOneToMany || relationIdAttr.relation.isOneToOneNotOwner) {
|
||||
// example: Post and Category
|
||||
// loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
// we expect it to load array of post ids
|
||||
// loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
// we expect it to load array of category ids
|
||||
|
||||
// todo: take post ids - they can be multiple
|
||||
// todo: create test with multiple primary columns usage
|
||||
const relation = relationIdAttr.relation; // "post.categories"
|
||||
const inverseRelation = relation.inverseRelation; // "category.post"
|
||||
const joinColumns = relation.isOwning ? relation.joinColumns : inverseRelation.joinColumns;
|
||||
const table = relation.inverseEntityMetadata.target; // category
|
||||
const tableName = relation.inverseEntityMetadata.tableName; // category
|
||||
const tableAlias = relationIdAttr.alias || tableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined
|
||||
|
||||
const relation = relationIdAttr.relation; // "category.posts"
|
||||
const inverseRelation = relation.inverseRelation; // "post.category"
|
||||
const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn!.propertyName; // post id
|
||||
const inverseSideTable = relation.inverseEntityMetadata.target; // Post
|
||||
const inverseSideTableName = relation.inverseEntityMetadata.tableName; // post
|
||||
const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined
|
||||
const inverseSidePropertyName = inverseRelation.propertyPath; // "category" from "post.category"
|
||||
|
||||
const referenceColumnValues = rawEntities
|
||||
.map(rawEntity => rawEntity[relationIdAttr.parentAlias + "_" + referenceColumnName])
|
||||
.filter(value => !!value);
|
||||
|
||||
/*const idMaps = rawEntities.map(rawEntity => {
|
||||
return this.createIdMap(relationIdAttr.relation.entityMetadata.primaryColumns, relationIdAttr.parentAlias, rawEntity);
|
||||
});*/
|
||||
const parameters: ObjectLiteral = {};
|
||||
const condition = rawEntities.map((rawEntity, index) => {
|
||||
return joinColumns.map(joinColumn => {
|
||||
const parameterName = joinColumn.databaseName + index;
|
||||
parameters[parameterName] = rawEntity[relationIdAttr.parentAlias + "_" + joinColumn.referencedColumn!.databaseName];
|
||||
return tableAlias + "." + joinColumn.databaseName + " = :" + parameterName;
|
||||
}).join(" AND ");
|
||||
}).map(condition => "(" + condition + ")")
|
||||
.join(" OR ");
|
||||
|
||||
// ensure we won't perform redundant queries for joined data which was not found in selection
|
||||
// example: if post.category was not found in db then no need to execute query for category.imageIds
|
||||
if (referenceColumnValues.length === 0)
|
||||
if (!condition)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
// const joinParameters: ObjectLiteral = {};
|
||||
/*const joinCondition = idMaps.map((idMap, idMapIndex) => {
|
||||
return "(" + Object.keys(idMap).map((idName, idIndex) => {
|
||||
const parameterName = `var${idMapIndex}_${idIndex}`;
|
||||
joinParameters[parameterName] = idMap[idName];
|
||||
return `${inverseSidePropertyName}.${idName} = :${parameterName}`
|
||||
}).join(" AND ") + ")";
|
||||
}).join(" OR ");*/
|
||||
|
||||
// generate query:
|
||||
// SELECT post.id AS id, category.id AS parentId FROM post post INNER JOIN category category ON category.id=post.category AND category.id IN [:categoryIds]
|
||||
// SELECT category.id, category.postId FROM category category ON category.postId = :postId
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider);
|
||||
qb.select(inverseSideTableAlias + "." + inverseSidePropertyName, "manyToManyId");
|
||||
|
||||
inverseRelation.entityMetadata.primaryColumns.forEach(primaryColumn => {
|
||||
qb.addSelect(inverseSideTableAlias + "." + primaryColumn.databaseName, inverseSideTableAlias + "_" + primaryColumn.databaseName);
|
||||
joinColumns.forEach(joinColumn => {
|
||||
qb.addSelect(tableAlias + "." + joinColumn.databaseName, joinColumn.databaseName);
|
||||
});
|
||||
|
||||
qb.from(inverseSideTable, inverseSideTableAlias)
|
||||
.where(inverseSideTableAlias + "." + inverseSidePropertyName + " IN (:ids)")
|
||||
.setParameter("ids", referenceColumnValues);
|
||||
inverseRelation.entityMetadata.primaryColumns.forEach(primaryColumn => {
|
||||
qb.addSelect(tableAlias + "." + primaryColumn.databaseName, primaryColumn.databaseName);
|
||||
});
|
||||
|
||||
qb.from(table, tableAlias)
|
||||
.where("(" + condition + ")") // need brackets because if we have additional condition and no brackets, it looks like (a = 1) OR (a = 2) AND b = 1, that is incorrect
|
||||
.setParameters(parameters);
|
||||
|
||||
// apply condition (custom query builder factory)
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
relationIdAttr.queryBuilderFactory(qb);
|
||||
|
||||
const relationIdRawResults: any[] = await qb.getRawMany();
|
||||
|
||||
const results: { id: any[], parentId: any, manyToManyId?: any }[] = [];
|
||||
relationIdRawResults.forEach(rawResult => {
|
||||
let result = results.find(result => result.manyToManyId === rawResult["manyToManyId"]);
|
||||
if (!result) {
|
||||
result = { id: [], parentId: "", manyToManyId: rawResult["manyToManyId"] };
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
if (inverseRelation.entityMetadata.primaryColumns.length === 1) {
|
||||
result.id.push(rawResult[inverseSideTableAlias + "_" + inverseRelation.entityMetadata.firstPrimaryColumn.databaseName]);
|
||||
} else {
|
||||
result.id.push(inverseRelation.entityMetadata.primaryColumns.reduce((ids, primaryColumn) => {
|
||||
ids[primaryColumn.propertyName] = rawResult[inverseSideTableAlias + "_" + primaryColumn.databaseName];
|
||||
return ids;
|
||||
}, {} as ObjectLiteral));
|
||||
}
|
||||
if (inverseRelation.isOneToOne) {
|
||||
result.id = result.id[0];
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
relationIdAttribute: relationIdAttr,
|
||||
results: results
|
||||
results: await qb.getRawMany()
|
||||
};
|
||||
|
||||
} else {
|
||||
@ -134,66 +103,60 @@ export class RelationIdLoader {
|
||||
// inverse side: loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
// we expect it to load array of post ids
|
||||
|
||||
let joinTableColumnName: string;
|
||||
let inverseJoinColumnName: string;
|
||||
let firstJunctionColumn: ColumnMetadata;
|
||||
let secondJunctionColumn: ColumnMetadata;
|
||||
|
||||
if (relationIdAttr.relation.isOwning) { // todo fix joinColumns[0]
|
||||
joinTableColumnName = relationIdAttr.relation.joinColumns[0].referencedColumn!.databaseName;
|
||||
inverseJoinColumnName = relationIdAttr.relation.joinColumns[0].referencedColumn!.databaseName;
|
||||
firstJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[0];
|
||||
secondJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[1];
|
||||
|
||||
} else {
|
||||
joinTableColumnName = relationIdAttr.relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
inverseJoinColumnName = relationIdAttr.relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
firstJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[1];
|
||||
secondJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[0];
|
||||
}
|
||||
|
||||
const referenceColumnValues = rawEntities
|
||||
.map(rawEntity => rawEntity[relationIdAttr.parentAlias + "_" + joinTableColumnName])
|
||||
.filter(value => value);
|
||||
|
||||
// ensure we won't perform redundant queries for joined data which was not found in selection
|
||||
// example: if post.category was not found in db then no need to execute query for category.imageIds
|
||||
if (referenceColumnValues.length === 0)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
const relation = relationIdAttr.relation;
|
||||
const joinColumns = relation.isOwning ? relation.joinColumns : relation.inverseRelation.inverseJoinColumns;
|
||||
const inverseJoinColumns = relation.isOwning ? relation.inverseJoinColumns : relation.inverseRelation.joinColumns;
|
||||
const junctionAlias = relationIdAttr.junctionAlias;
|
||||
const inverseSideTableName = relationIdAttr.joinInverseSideMetadata.tableName;
|
||||
const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName;
|
||||
const junctionTableName = relationIdAttr.relation.junctionEntityMetadata.tableName;
|
||||
const condition = junctionAlias + "." + firstJunctionColumn.propertyPath + " IN (" + referenceColumnValues + ")" +
|
||||
" AND " + junctionAlias + "." + secondJunctionColumn.propertyPath + " = " + inverseSideTableAlias + "." + inverseJoinColumnName;
|
||||
const junctionTableName = relation.junctionEntityMetadata.tableName;
|
||||
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider)
|
||||
.select(inverseSideTableAlias + "." + inverseJoinColumnName, "id")
|
||||
.addSelect(junctionAlias + "." + firstJunctionColumn.propertyPath, "manyToManyId")
|
||||
.fromTable(inverseSideTableName, inverseSideTableAlias)
|
||||
const mappedColumns = rawEntities.map(rawEntity => {
|
||||
return joinColumns.reduce((map, joinColumn) => {
|
||||
map[joinColumn.databaseName] = rawEntity[relationIdAttr.parentAlias + "_" + joinColumn.referencedColumn!.databaseName];
|
||||
return map;
|
||||
}, {} as ObjectLiteral);
|
||||
});
|
||||
|
||||
// ensure we won't perform redundant queries for joined data which was not found in selection
|
||||
// example: if post.category was not found in db then no need to execute query for category.imageIds
|
||||
if (mappedColumns.length === 0)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
const joinColumnConditions = mappedColumns.map(mappedColumn => {
|
||||
return Object.keys(mappedColumn).map(key => {
|
||||
return junctionAlias + "." + key + " = " + mappedColumn[key];
|
||||
}).join(" AND ");
|
||||
});
|
||||
|
||||
const inverseJoinColumnCondition = inverseJoinColumns.map(joinColumn => {
|
||||
return junctionAlias + "." + joinColumn.databaseName + " = " + inverseSideTableAlias + "." + joinColumn.referencedColumn!.databaseName;
|
||||
}).join(" AND ");
|
||||
|
||||
const condition = joinColumnConditions.map(condition => {
|
||||
return "(" + condition + " AND " + inverseJoinColumnCondition + ")";
|
||||
}).join(" OR ");
|
||||
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider);
|
||||
|
||||
inverseJoinColumns.forEach(joinColumn => {
|
||||
qb.addSelect(junctionAlias + "." + joinColumn.databaseName, joinColumn.databaseName);
|
||||
});
|
||||
|
||||
joinColumns.forEach(joinColumn => {
|
||||
qb.addSelect(junctionAlias + "." + joinColumn.databaseName, joinColumn.databaseName);
|
||||
});
|
||||
|
||||
qb.fromTable(inverseSideTableName, inverseSideTableAlias)
|
||||
.innerJoin(junctionTableName, junctionAlias, condition);
|
||||
|
||||
// apply condition (custom query builder factory)
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
relationIdAttr.queryBuilderFactory(qb);
|
||||
|
||||
const relationIdRawResults: any[] = await qb.getRawMany();
|
||||
|
||||
const results: { id: any[], parentId: any, manyToManyId?: any }[] = [];
|
||||
relationIdRawResults.forEach(rawResult => {
|
||||
let result = results.find(result => result.manyToManyId === rawResult["manyToManyId"]);
|
||||
if (!result) {
|
||||
result = { id: [], parentId: "", manyToManyId: rawResult["manyToManyId"] };
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
result.id.push(rawResult["id"]);
|
||||
});
|
||||
|
||||
return {
|
||||
relationIdAttribute: relationIdAttr,
|
||||
results: results
|
||||
results: await qb.getRawMany()
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
218
src/query-builder/relation-id/RelationIdLoaderOld.ts
Normal file
218
src/query-builder/relation-id/RelationIdLoaderOld.ts
Normal file
@ -0,0 +1,218 @@
|
||||
import {RelationIdAttribute} from "./RelationIdAttribute";
|
||||
import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {QueryBuilder} from "../QueryBuilder";
|
||||
import {Connection} from "../../connection/Connection";
|
||||
import {QueryRunnerProvider} from "../../query-runner/QueryRunnerProvider";
|
||||
import {RelationIdLoadResult} from "./RelationIdLoadResult";
|
||||
import {ObjectLiteral} from "../../common/ObjectLiteral";
|
||||
|
||||
export class RelationIdLoaderOld {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(protected connection: Connection,
|
||||
protected queryRunnerProvider: QueryRunnerProvider|undefined,
|
||||
protected relationIdAttributes: RelationIdAttribute[]) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
async load(rawEntities: any[]): Promise<RelationIdLoadResult[]> {
|
||||
|
||||
const promises = this.relationIdAttributes.map(async relationIdAttr => {
|
||||
|
||||
if (relationIdAttr.relation.isManyToOne || relationIdAttr.relation.isOneToOneOwner) {
|
||||
// example: Post and Tag
|
||||
// loadRelationIdAndMap("post.tagId", "post.tag") post_tag
|
||||
// we expect it to load id of tag
|
||||
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
throw new Error(""); // todo: fix
|
||||
|
||||
const results = rawEntities.map(rawEntity => {
|
||||
return {
|
||||
id: rawEntity[relationIdAttr.parentAlias + "_" + relationIdAttr.relation.name],
|
||||
parentId: this.createIdMap(relationIdAttr.relation.entityMetadata.primaryColumns, relationIdAttr.parentAlias, rawEntity)
|
||||
};
|
||||
});
|
||||
|
||||
return {
|
||||
relationIdAttribute: relationIdAttr,
|
||||
results: results
|
||||
};
|
||||
|
||||
} else if (relationIdAttr.relation.isOneToMany || relationIdAttr.relation.isOneToOneNotOwner) {
|
||||
// example: Post and Category
|
||||
// loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
// we expect it to load array of post ids
|
||||
|
||||
// todo: take post ids - they can be multiple
|
||||
// todo: create test with multiple primary columns usage
|
||||
|
||||
const relation = relationIdAttr.relation; // "category.posts"
|
||||
const inverseRelation = relation.inverseRelation; // "post.category"
|
||||
const referenceColumnName = inverseRelation.joinColumns[0].referencedColumn!.propertyName; // post id
|
||||
const inverseSideTable = relation.inverseEntityMetadata.target; // Post
|
||||
const inverseSideTableName = relation.inverseEntityMetadata.tableName; // post
|
||||
const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName; // if condition (custom query builder factory) is set then relationIdAttr.alias defined
|
||||
const inverseSidePropertyName = inverseRelation.propertyPath; // "category" from "post.category"
|
||||
|
||||
const referenceColumnValues = rawEntities
|
||||
.map(rawEntity => rawEntity[relationIdAttr.parentAlias + "_" + referenceColumnName])
|
||||
.filter(value => !!value);
|
||||
|
||||
/*const idMaps = rawEntities.map(rawEntity => {
|
||||
return this.createIdMap(relationIdAttr.relation.entityMetadata.primaryColumns, relationIdAttr.parentAlias, rawEntity);
|
||||
});*/
|
||||
|
||||
// ensure we won't perform redundant queries for joined data which was not found in selection
|
||||
// example: if post.category was not found in db then no need to execute query for category.imageIds
|
||||
if (referenceColumnValues.length === 0)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
// const joinParameters: ObjectLiteral = {};
|
||||
/*const joinCondition = idMaps.map((idMap, idMapIndex) => {
|
||||
return "(" + Object.keys(idMap).map((idName, idIndex) => {
|
||||
const parameterName = `var${idMapIndex}_${idIndex}`;
|
||||
joinParameters[parameterName] = idMap[idName];
|
||||
return `${inverseSidePropertyName}.${idName} = :${parameterName}`
|
||||
}).join(" AND ") + ")";
|
||||
}).join(" OR ");*/
|
||||
|
||||
// generate query:
|
||||
// SELECT post.id AS id, category.id AS parentId FROM post post INNER JOIN category category ON category.id=post.category AND category.id IN [:categoryIds]
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider);
|
||||
qb.select(inverseSideTableAlias + "." + inverseSidePropertyName, "manyToManyId");
|
||||
|
||||
inverseRelation.entityMetadata.primaryColumns.forEach(primaryColumn => {
|
||||
qb.addSelect(inverseSideTableAlias + "." + primaryColumn.databaseName, inverseSideTableAlias + "_" + primaryColumn.databaseName);
|
||||
});
|
||||
|
||||
qb.from(inverseSideTable, inverseSideTableAlias)
|
||||
.where(inverseSideTableAlias + "." + inverseSidePropertyName + " IN (:ids)")
|
||||
.setParameter("ids", referenceColumnValues);
|
||||
|
||||
// apply condition (custom query builder factory)
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
relationIdAttr.queryBuilderFactory(qb);
|
||||
|
||||
const relationIdRawResults: any[] = await qb.getRawMany();
|
||||
|
||||
const results: { id: any[], parentId: any, manyToManyId?: any }[] = [];
|
||||
relationIdRawResults.forEach(rawResult => {
|
||||
let result = results.find(result => result.manyToManyId === rawResult["manyToManyId"]);
|
||||
if (!result) {
|
||||
result = { id: [], parentId: "", manyToManyId: rawResult["manyToManyId"] };
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
if (inverseRelation.entityMetadata.primaryColumns.length === 1) {
|
||||
result.id.push(rawResult[inverseSideTableAlias + "_" + inverseRelation.entityMetadata.firstPrimaryColumn.databaseName]);
|
||||
} else {
|
||||
result.id.push(inverseRelation.entityMetadata.primaryColumns.reduce((ids, primaryColumn) => {
|
||||
ids[primaryColumn.propertyName] = rawResult[inverseSideTableAlias + "_" + primaryColumn.databaseName];
|
||||
return ids;
|
||||
}, {} as ObjectLiteral));
|
||||
}
|
||||
if (inverseRelation.isOneToOne) {
|
||||
result.id = result.id[0];
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
relationIdAttribute: relationIdAttr,
|
||||
results: results
|
||||
};
|
||||
|
||||
} else {
|
||||
// example: Post and Category
|
||||
// owner side: loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
// inverse side: loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
// we expect it to load array of post ids
|
||||
|
||||
let joinTableColumnName: string;
|
||||
let inverseJoinColumnName: string;
|
||||
let firstJunctionColumn: ColumnMetadata;
|
||||
let secondJunctionColumn: ColumnMetadata;
|
||||
|
||||
if (relationIdAttr.relation.isOwning) { // todo fix joinColumns[0]
|
||||
joinTableColumnName = relationIdAttr.relation.joinColumns[0].referencedColumn!.databaseName;
|
||||
inverseJoinColumnName = relationIdAttr.relation.joinColumns[0].referencedColumn!.databaseName;
|
||||
firstJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[0];
|
||||
secondJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[1];
|
||||
|
||||
} else {
|
||||
joinTableColumnName = relationIdAttr.relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
inverseJoinColumnName = relationIdAttr.relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
firstJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[1];
|
||||
secondJunctionColumn = relationIdAttr.relation.junctionEntityMetadata.columns[0];
|
||||
}
|
||||
|
||||
const referenceColumnValues = rawEntities
|
||||
.map(rawEntity => rawEntity[relationIdAttr.parentAlias + "_" + joinTableColumnName])
|
||||
.filter(value => value);
|
||||
|
||||
// ensure we won't perform redundant queries for joined data which was not found in selection
|
||||
// example: if post.category was not found in db then no need to execute query for category.imageIds
|
||||
if (referenceColumnValues.length === 0)
|
||||
return { relationIdAttribute: relationIdAttr, results: [] };
|
||||
|
||||
const junctionAlias = relationIdAttr.junctionAlias;
|
||||
const inverseSideTableName = relationIdAttr.joinInverseSideMetadata.tableName;
|
||||
const inverseSideTableAlias = relationIdAttr.alias || inverseSideTableName;
|
||||
const junctionTableName = relationIdAttr.relation.junctionEntityMetadata.tableName;
|
||||
const condition = junctionAlias + "." + firstJunctionColumn.propertyPath + " IN (" + referenceColumnValues + ")" +
|
||||
" AND " + junctionAlias + "." + secondJunctionColumn.propertyPath + " = " + inverseSideTableAlias + "." + inverseJoinColumnName;
|
||||
|
||||
/* const firstJunctionColumnConditions = firstJunctionColumns.map(joinColumn => {
|
||||
return `${junctionAlias}.${joinColumn.propertyPath} = :${joinColumn.propertyPath}`;
|
||||
});
|
||||
const secondJunctionColumnConditions = secondJunctionColumns.map(joinColumn => {
|
||||
return `${junctionAlias}.${joinColumn.propertyPath} = :${joinColumn.propertyPath}`;
|
||||
});*/
|
||||
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider)
|
||||
.select(inverseSideTableAlias + "." + inverseJoinColumnName, "id")
|
||||
.addSelect(junctionAlias + "." + firstJunctionColumn.propertyPath, "manyToManyId")
|
||||
.fromTable(inverseSideTableName, inverseSideTableAlias)
|
||||
.innerJoin(junctionTableName, junctionAlias, condition);
|
||||
|
||||
// apply condition (custom query builder factory)
|
||||
if (relationIdAttr.queryBuilderFactory)
|
||||
relationIdAttr.queryBuilderFactory(qb);
|
||||
|
||||
const relationIdRawResults: any[] = await qb.getRawMany();
|
||||
|
||||
const results: { id: any[], parentId: any, manyToManyId?: any }[] = [];
|
||||
relationIdRawResults.forEach(rawResult => {
|
||||
let result = results.find(result => result.manyToManyId === rawResult["manyToManyId"]);
|
||||
if (!result) {
|
||||
result = { id: [], parentId: "", manyToManyId: rawResult["manyToManyId"] };
|
||||
results.push(result);
|
||||
}
|
||||
|
||||
result.id.push(rawResult["id"]);
|
||||
});
|
||||
|
||||
return {
|
||||
relationIdAttribute: relationIdAttr,
|
||||
results: results
|
||||
};
|
||||
}
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
protected createIdMap(columns: ColumnMetadata[], parentAlias: string, rawEntity: any) {
|
||||
return columns.reduce((idMap, primaryColumn) => {
|
||||
idMap[primaryColumn.propertyName] = rawEntity[parentAlias + "_" + primaryColumn.databaseName];
|
||||
return idMap;
|
||||
}, {} as ObjectLiteral);
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,6 +5,7 @@ import {ColumnMetadata} from "../../metadata/ColumnMetadata";
|
||||
import {Alias} from "../Alias";
|
||||
import {JoinAttribute} from "../JoinAttribute";
|
||||
import {RelationCountLoadResult} from "../relation-count/RelationCountLoadResult";
|
||||
import {RelationMetadata} from "../../metadata/RelationMetadata";
|
||||
|
||||
/**
|
||||
* Transforms raw sql results returned from the database into entity object.
|
||||
@ -142,7 +143,9 @@ export class RawSqlResultsToEntityTransformer {
|
||||
return;
|
||||
|
||||
const relation = rawRelationIdResult.relationIdAttribute.relation;
|
||||
let idMap: any, referenceColumnValue: any;
|
||||
let idMap: any;
|
||||
let valueMap: ObjectLiteral;
|
||||
|
||||
if (relation.isManyToOne || relation.isOneToOneOwner) {
|
||||
idMap = relation.entityMetadata.primaryColumns.reduce((idMap, primaryColumn) => {
|
||||
idMap[primaryColumn.propertyName] = rawSqlResults[0][alias.name + "_" + primaryColumn.databaseName];
|
||||
@ -150,26 +153,68 @@ export class RawSqlResultsToEntityTransformer {
|
||||
}, {} as ObjectLiteral);
|
||||
|
||||
} else {
|
||||
let referenceColumnName: string;
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) { // todo: fix joinColumns[0]
|
||||
referenceColumnName = relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) {
|
||||
valueMap = this.createValueMapFromJoinColumns(relation, entity);
|
||||
} else {
|
||||
referenceColumnName = relation.isOwning ? relation.joinColumns[0].referencedColumn!.databaseName : relation.inverseRelation.joinColumns[0].referencedColumn!.databaseName;
|
||||
valueMap = this.createValueMapFromJoinColumns(relation, entity);
|
||||
}
|
||||
referenceColumnValue = rawSqlResults[0][alias.name + "_" + referenceColumnName];
|
||||
/* referenceColumnValue = rawSqlResults[0][alias.name + "_" + referenceColumnName];
|
||||
if (referenceColumnValue === undefined || referenceColumnValue === null)
|
||||
return;*/
|
||||
if (valueMap === undefined || valueMap === null)
|
||||
return;
|
||||
}
|
||||
|
||||
rawRelationIdResult.results.forEach(result => {
|
||||
if (result.parentId && !alias.metadata.compareIds(result.parentId, idMap))
|
||||
const referencedColumnResults = rawRelationIdResult.results.map(result => {
|
||||
/* if (result.parentId && !alias.metadata.compareIds(result.parentId, idMap))
|
||||
return;
|
||||
if (result.manyToManyId && result.manyToManyId !== referenceColumnValue)
|
||||
return;*/
|
||||
|
||||
const entityPrimaryIds = this.extractEntityPrimaryIds(relation, result);
|
||||
if (!alias.metadata.compareIds(entityPrimaryIds, valueMap))
|
||||
return;
|
||||
|
||||
entity[rawRelationIdResult.relationIdAttribute.mapToPropertyPropertyName] = result.id;
|
||||
hasData = true;
|
||||
});
|
||||
let joinColumns: ColumnMetadata[];
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) {
|
||||
joinColumns = relation.inverseEntityMetadata.primaryColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
if (relation.isManyToManyOwner) {
|
||||
joinColumns = relation.inverseJoinColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
joinColumns = relation.inverseRelation.joinColumns.map(joinColumn => joinColumn);
|
||||
}
|
||||
}
|
||||
|
||||
return joinColumns.reduce((referencedColumnResult, joinColumn) => {
|
||||
if (joinColumns.length > 1) {
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) {
|
||||
referencedColumnResult[joinColumn.propertyName] = result[joinColumn.databaseName];
|
||||
} else {
|
||||
referencedColumnResult[joinColumn.referencedColumn!.propertyName] = result[joinColumn.databaseName];
|
||||
}
|
||||
} else {
|
||||
referencedColumnResult = result[joinColumn.databaseName];
|
||||
}
|
||||
return referencedColumnResult;
|
||||
}, {} as ObjectLiteral);
|
||||
}).filter(result => result);
|
||||
|
||||
const properties = rawRelationIdResult.relationIdAttribute.mapToPropertyPropertyPath.split(".");
|
||||
const mapToProperty = (properties: string[], map: ObjectLiteral, value: any): any => {
|
||||
|
||||
const property = properties.shift();
|
||||
if (property && properties.length === 0) {
|
||||
map[property] = value;
|
||||
return map;
|
||||
} else if (property && properties.length > 0) {
|
||||
mapToProperty(properties, map[property], value);
|
||||
} else {
|
||||
return map;
|
||||
}
|
||||
};
|
||||
mapToProperty(properties, entity, referencedColumnResults);
|
||||
hasData = true;
|
||||
});
|
||||
return hasData;
|
||||
}
|
||||
@ -204,4 +249,39 @@ export class RawSqlResultsToEntityTransformer {
|
||||
return hasData;
|
||||
}
|
||||
|
||||
private createValueMapFromJoinColumns(relation: RelationMetadata, entity: ObjectLiteral): ObjectLiteral {
|
||||
let joinColumns: ColumnMetadata[];
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) {
|
||||
joinColumns = relation.inverseRelation.joinColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
if (relation.isOwning) {
|
||||
joinColumns = relation.joinColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
joinColumns = relation.inverseRelation.inverseJoinColumns.map(joinColumn => joinColumn);
|
||||
}
|
||||
}
|
||||
return joinColumns.reduce((valueMap, joinColumn) => {
|
||||
valueMap[joinColumn.databaseName] = joinColumn.referencedColumn!.getEntityValue(entity);
|
||||
return valueMap;
|
||||
}, {} as ObjectLiteral);
|
||||
|
||||
}
|
||||
|
||||
private extractEntityPrimaryIds(relation: RelationMetadata, relationIdRawResult: any) {
|
||||
let joinColumns: ColumnMetadata[];
|
||||
if (relation.isOneToMany || relation.isOneToOneNotOwner) {
|
||||
joinColumns = relation.inverseRelation.joinColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
if (relation.isOwning) {
|
||||
joinColumns = relation.joinColumns.map(joinColumn => joinColumn);
|
||||
} else {
|
||||
joinColumns = relation.inverseRelation.inverseJoinColumns.map(joinColumn => joinColumn);
|
||||
}
|
||||
}
|
||||
return joinColumns.reduce((data, joinColumn) => {
|
||||
data[joinColumn.databaseName] = relationIdRawResult[joinColumn.databaseName];
|
||||
return data;
|
||||
}, {} as ObjectLiteral);
|
||||
}
|
||||
|
||||
}
|
||||
@ -6,6 +6,7 @@ import {Subject} from "../persistence/Subject";
|
||||
import {RelationMetadata} from "../metadata/RelationMetadata";
|
||||
import {ColumnMetadata} from "../metadata/ColumnMetadata";
|
||||
import {QueryBuilder} from "../query-builder/QueryBuilder";
|
||||
import {OrmUtils} from "../util/OrmUtils";
|
||||
|
||||
/**
|
||||
* Repository for more specific operations.
|
||||
@ -439,6 +440,8 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
|
||||
const ec = (column: string) => this.connection.driver.escapeColumnName(column);
|
||||
|
||||
let ids: any[] = [];
|
||||
console.log("entityOrEntities:", entityOrEntities);
|
||||
// console.log("entityIds:", entityIds);
|
||||
const promises = (entityIds as any[]).map((entityId: any) => {
|
||||
const qb = new QueryBuilder(this.connection, this.queryRunnerProvider);
|
||||
inverseEntityColumnNames.forEach(columnName => {
|
||||
@ -460,12 +463,14 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
|
||||
// if (notInIds && notInIds.length > 0)
|
||||
// qb.andWhere(ea("junction") + "." + ec(inverseEntityColumnNames.fullName) + " NOT IN (:notInIds)", {notInIds: notInIds});
|
||||
|
||||
// console.log(qb.getSql());
|
||||
return qb.getRawMany()
|
||||
.then((results: any[]) => {
|
||||
// console.log(results);
|
||||
results.forEach(result => {
|
||||
ids.push(Object.keys(result).reduce((id, key) => {
|
||||
const junctionColumnName = inverseEntityColumns.find(joinColumn => joinColumn.databaseName === key)!;
|
||||
id[junctionColumnName.referencedColumn!.propertyName] = result[key];
|
||||
OrmUtils.mergeDeep(id, junctionColumnName.referencedColumn!.createValueMap(result[key]));
|
||||
return id;
|
||||
}, {} as ObjectLiteral));
|
||||
}); // todo: prepare result?
|
||||
@ -490,7 +495,7 @@ export class SpecificRepository<Entity extends ObjectLiteral> {
|
||||
} else {
|
||||
if (entityOrEntities instanceof Object) {
|
||||
return columns.reduce((ids, column) => {
|
||||
ids[column.databaseName] = entityOrEntities[column.propertyName];
|
||||
ids[column.databaseName] = column.getEntityValue(entityOrEntities);
|
||||
return ids;
|
||||
}, {} as ObjectLiteral);
|
||||
} else {
|
||||
|
||||
39
test/benchmark/bulk-save/bulk-save.ts
Normal file
39
test/benchmark/bulk-save/bulk-save.ts
Normal file
@ -0,0 +1,39 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {Connection} from "../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../utils/test-utils";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe.skip("benchmark > bulk-save", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
|
||||
it("testing bulk save of 100 objects", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const posts: Post[] = [];
|
||||
|
||||
for(let i = 1; i <= 100; i++) {
|
||||
const post = new Post();
|
||||
post.title = `Post #${i}`;
|
||||
post.text = `Post #${i} text`;
|
||||
post.likesCount = i;
|
||||
post.commentsCount = i;
|
||||
post.watchesCount = i;
|
||||
posts.push(post);
|
||||
}
|
||||
|
||||
await connection.manager.persist(posts);
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
26
test/benchmark/bulk-save/entity/Post.ts
Normal file
26
test/benchmark/bulk-save/entity/Post.ts
Normal file
@ -0,0 +1,26 @@
|
||||
import {Entity} from "../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column({ type: "text" })
|
||||
text: string;
|
||||
|
||||
@Column({ type: "int" })
|
||||
likesCount: number;
|
||||
|
||||
@Column({ type: "int" })
|
||||
commentsCount: number;
|
||||
|
||||
@Column({ type: "int" })
|
||||
watchesCount: number;
|
||||
|
||||
}
|
||||
@ -24,27 +24,27 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "cars";
|
||||
await connection.entityManager.persist(category3);
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about BMW";
|
||||
post2.categories = [category3];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.getMany();
|
||||
|
||||
@ -54,7 +54,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
expect(loadedPosts![1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
.getOne();
|
||||
@ -69,29 +69,29 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
category2.isRemoved = true;
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "cars";
|
||||
category3.isRemoved = true;
|
||||
await connection.entityManager.persist(category3);
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about BMW";
|
||||
post2.categories = [category3];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.getMany();
|
||||
|
||||
@ -101,7 +101,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
expect(loadedPosts![1].removedCategoryIds).to.not.be.empty;
|
||||
expect(loadedPosts![1].removedCategoryIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
@ -116,18 +116,18 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.subcategories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
.getOne();
|
||||
@ -142,19 +142,19 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
category2.isRemoved = true;
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.subcategories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
.getOne();
|
||||
@ -169,19 +169,19 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.categories = [category];
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.categories = [category];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.where("category.id = :id", { id: category.id })
|
||||
.getOne();
|
||||
@ -196,20 +196,20 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.categories = [category];
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.isRemoved = true;
|
||||
post2.categories = [category];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.where("category.id = :id", { id: category.id })
|
||||
.getOne();
|
||||
@ -224,41 +224,41 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
await connection.entityManager.persist(image1);
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "photo2";
|
||||
await connection.entityManager.persist(image2);
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const image3 = new Image();
|
||||
image3.name = "photo2";
|
||||
await connection.entityManager.persist(image3);
|
||||
await connection.manager.persist(image3);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "Audi";
|
||||
category3.images = [image3];
|
||||
await connection.entityManager.persist(category3);
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.categories = [category3];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.addOrderBy("post.id, categories.id")
|
||||
@ -281,7 +281,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
expect(loadedPosts![1].categories[0].imageIds.length).to.be.equal(1);
|
||||
expect(loadedPosts![1].categories[0].imageIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.addOrderBy("post.id, categories.id")
|
||||
@ -304,23 +304,23 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
await connection.entityManager.persist(image1);
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "photo2";
|
||||
await connection.entityManager.persist(image2);
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories", "categories.id = :categoryId")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
@ -336,45 +336,45 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "photo1";
|
||||
await connection.entityManager.persist(image1);
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "photo2";
|
||||
image2.isRemoved = true;
|
||||
await connection.entityManager.persist(image2);
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const image3 = new Image();
|
||||
image3.name = "photo2";
|
||||
image3.isRemoved = true;
|
||||
await connection.entityManager.persist(image3);
|
||||
await connection.manager.persist(image3);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
category2.isRemoved = true;
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "BMW";
|
||||
category3.isRemoved = true;
|
||||
category3.images = [image3];
|
||||
await connection.entityManager.persist(category3);
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about BMW";
|
||||
post2.categories = [category3];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.addOrderBy("post.id, categories.id")
|
||||
@ -395,7 +395,7 @@ describe("decorators > relation-id-decorator > many-to-many", () => {
|
||||
expect(loadedPosts![1].categories[0].removedImageIds.length).to.be.equal(1);
|
||||
expect(loadedPosts![1].categories[0].removedImageIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.addOrderBy("post.id, categories.id")
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
@ -23,33 +23,33 @@ describe("decorators > relation-id-decorator > many-to-one", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const categoryByName1 = new Category();
|
||||
categoryByName1.name = "BMW";
|
||||
await connection.entityManager.persist(categoryByName1);
|
||||
await connection.manager.persist(categoryByName1);
|
||||
|
||||
const categoryByName2 = new Category();
|
||||
categoryByName2.name = "Boeing";
|
||||
await connection.entityManager.persist(categoryByName2);
|
||||
await connection.manager.persist(categoryByName2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BWM";
|
||||
post1.category = category1;
|
||||
post1.categoryByName = categoryByName1;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Boeing";
|
||||
post2.category = category2;
|
||||
post2.categoryByName = categoryByName2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.getMany();
|
||||
|
||||
@ -62,7 +62,7 @@ describe("decorators > relation-id-decorator > many-to-one", () => {
|
||||
expect(loadedPosts![1].categoryName).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryName).to.be.equal("Boeing");
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -23,28 +23,28 @@ describe("decorators > relation-id > one-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category = category;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.category = category;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.title = "about Boeing";
|
||||
post3.category = category2;
|
||||
await connection.entityManager.persist(post3);
|
||||
await connection.manager.persist(post3);
|
||||
|
||||
let loadedCategories = await connection.entityManager
|
||||
let loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.getMany();
|
||||
|
||||
@ -54,7 +54,7 @@ describe("decorators > relation-id > one-to-many", () => {
|
||||
expect(loadedCategories![1].postIds.length).to.be.equal(1);
|
||||
expect(loadedCategories![1].postIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
@ -68,30 +68,30 @@ describe("decorators > relation-id > one-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category = category;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.category = category;
|
||||
post2.isRemoved = true;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.title = "about Boeing";
|
||||
post3.category = category2;
|
||||
post3.isRemoved = true;
|
||||
await connection.entityManager.persist(post3);
|
||||
await connection.manager.persist(post3);
|
||||
|
||||
let loadedCategories = await connection.entityManager
|
||||
let loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.getMany();
|
||||
|
||||
@ -100,7 +100,7 @@ describe("decorators > relation-id > one-to-many", () => {
|
||||
expect(loadedCategories![0].removedPostIds[0]).to.be.equal(2);
|
||||
expect(loadedCategories![1].removedPostIds[0]).to.be.equal(3);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -23,33 +23,33 @@ describe("decorators > relation-id > one-to-one", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const categoryByName1 = new Category();
|
||||
categoryByName1.name = "BMW";
|
||||
await connection.entityManager.persist(categoryByName1);
|
||||
await connection.manager.persist(categoryByName1);
|
||||
|
||||
const categoryByName2 = new Category();
|
||||
categoryByName2.name = "Boeing";
|
||||
await connection.entityManager.persist(categoryByName2);
|
||||
await connection.manager.persist(categoryByName2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category = category1;
|
||||
post1.categoryByName = categoryByName1;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Boeing";
|
||||
post2.category = category2;
|
||||
post2.categoryByName = categoryByName2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.addOrderBy("post.id")
|
||||
.getMany();
|
||||
@ -63,7 +63,7 @@ describe("decorators > relation-id > one-to-one", () => {
|
||||
expect(loadedPosts![1].categoryName).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryName).to.be.equal("Boeing");
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
@ -78,23 +78,23 @@ describe("decorators > relation-id > one-to-one", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category2 = category1;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Boeing";
|
||||
post2.category2 = category2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedCategories = await connection.entityManager
|
||||
let loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.addOrderBy("category.id")
|
||||
.getMany();
|
||||
@ -104,7 +104,7 @@ describe("decorators > relation-id > one-to-one", () => {
|
||||
expect(loadedCategories![1].postId).to.not.be.empty;
|
||||
expect(loadedCategories![1].postId).to.be.equal(2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
@ -20,7 +20,7 @@ describe.skip("embedded > embedded-many-to-many-case3", () => {
|
||||
|
||||
describe("owner side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToMany relation with multiple primary keys (one PK en each embed)", () => Promise.all(connections.map(async connection => {
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToMany relation with multiple primary keys (one PK in each embed)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.name = "Alice";
|
||||
@ -197,7 +197,7 @@ describe.skip("embedded > embedded-many-to-many-case3", () => {
|
||||
|
||||
describe("inverse side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToMany relation with multiple primary keys (one PK en each embed)", () => Promise.all(connections.map(async connection => {
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToMany relation with multiple primary keys (one PK in each embed)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
|
||||
@ -20,7 +20,7 @@ describe("embedded > embedded-many-to-one-case3", () => {
|
||||
|
||||
describe("owner side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (one PK en each embed)", () => Promise.all(connections.map(async connection => {
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (one PK in each embed)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.name = "Alice";
|
||||
@ -168,7 +168,7 @@ describe("embedded > embedded-many-to-one-case3", () => {
|
||||
|
||||
describe("inverse side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (one PK en each embed)", () => Promise.all(connections.map(async connection => {
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (one PK in each embed)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
|
||||
@ -0,0 +1,389 @@
|
||||
import "reflect-metadata";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {expect} from "chai";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Subcounters} from "./entity/Subcounters";
|
||||
import {User} from "./entity/User";
|
||||
|
||||
describe("embedded > embedded-many-to-one-case5", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
describe("owner side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (multiple keys in both sides)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.personId = 1;
|
||||
user1.name = "Alice";
|
||||
await connection.getRepository(User).persist(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.personId = 2;
|
||||
user2.name = "Bob";
|
||||
await connection.getRepository(User).persist(user2);
|
||||
|
||||
const user3 = new User();
|
||||
user3.id = 3;
|
||||
user3.personId = 3;
|
||||
user3.name = "Clara";
|
||||
await connection.getRepository(User).persist(user3);
|
||||
|
||||
const postRepository = connection.getRepository(Post);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About cars";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 1;
|
||||
post1.counters.comments = 1;
|
||||
post1.counters.favorites = 2;
|
||||
post1.counters.likes = 3;
|
||||
post1.counters.likedUser = user1;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 5;
|
||||
await postRepository.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About airplanes";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 2;
|
||||
post2.counters.comments = 2;
|
||||
post2.counters.favorites = 3;
|
||||
post2.counters.likes = 4;
|
||||
post2.counters.likedUser = user2;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 10;
|
||||
await postRepository.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.counters.likedUser", "likedUser")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
likedUser: { id: 1, personId: 1, name: "Alice" },
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About airplanes",
|
||||
counters: {
|
||||
code: 2,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
likes: 4,
|
||||
likedUser: { id: 2, personId: 2, name: "Bob" },
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.counters.likedUser", "likedUser")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
likedUser: { id: 1, personId: 1, name: "Alice" },
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
loadedPost!.counters.favorites += 1;
|
||||
loadedPost!.counters.subcounters.watches += 1;
|
||||
loadedPost!.counters.likedUser = user3;
|
||||
await postRepository.persist(loadedPost!);
|
||||
|
||||
loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.counters.likedUser", "likedUser")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 3,
|
||||
likes: 3,
|
||||
likedUser: { id: 3, personId: 3, name: "Clara" },
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 6
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
await postRepository.remove(loadedPost!);
|
||||
|
||||
loadedPosts = (await postRepository.find())!;
|
||||
expect(loadedPosts.length).to.be.equal(1);
|
||||
expect(loadedPosts[0].title).to.be.equal("About airplanes");
|
||||
})));
|
||||
});
|
||||
|
||||
describe("inverse side", () => {
|
||||
|
||||
it("should insert, load, update and remove entities with embeddeds when embedded entity having ManyToOne relation with multiple primary keys (multiple keys in both sides)", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About cars";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.code = 1;
|
||||
post1.counters.comments = 1;
|
||||
post1.counters.favorites = 2;
|
||||
post1.counters.likes = 3;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.version = 1;
|
||||
post1.counters.subcounters.watches = 5;
|
||||
await connection.getRepository(Post).persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About airplanes";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.code = 2;
|
||||
post2.counters.comments = 2;
|
||||
post2.counters.favorites = 3;
|
||||
post2.counters.likes = 4;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.version = 1;
|
||||
post2.counters.subcounters.watches = 10;
|
||||
await connection.getRepository(Post).persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.id = 3;
|
||||
post3.title = "About horses";
|
||||
post3.counters = new Counters();
|
||||
post3.counters.code = 3;
|
||||
post3.counters.comments = 5;
|
||||
post3.counters.favorites = 10;
|
||||
post3.counters.likes = 15;
|
||||
post3.counters.subcounters = new Subcounters();
|
||||
post3.counters.subcounters.version = 1;
|
||||
post3.counters.subcounters.watches = 30;
|
||||
await connection.getRepository(Post).persist(post3);
|
||||
|
||||
const user1 = new User();
|
||||
user1.id = 1;
|
||||
user1.personId = 1;
|
||||
user1.name = "Alice";
|
||||
user1.likedPosts = [post1, post2];
|
||||
await connection.getRepository(User).persist(user1);
|
||||
|
||||
const user2 = new User();
|
||||
user2.id = 2;
|
||||
user2.personId = 2;
|
||||
user2.name = "Bob";
|
||||
user2.likedPosts = [post3];
|
||||
await connection.getRepository(User).persist(user2);
|
||||
|
||||
let loadedUsers = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPosts", "likedPost")
|
||||
.orderBy("user.id, likedPost.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedUsers[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
personId: 1,
|
||||
name: "Alice",
|
||||
likedPosts: [
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "About airplanes",
|
||||
counters: {
|
||||
code: 2,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
likes: 4,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
));
|
||||
expect(loadedUsers[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
personId: 2,
|
||||
name: "Bob",
|
||||
likedPosts: [
|
||||
{
|
||||
id: 3,
|
||||
title: "About horses",
|
||||
counters: {
|
||||
code: 3,
|
||||
comments: 5,
|
||||
favorites: 10,
|
||||
likes: 15,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 30
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
));
|
||||
|
||||
let loadedUser = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPosts", "likedPost")
|
||||
.orderBy("likedPost.id")
|
||||
.where("user.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedUser!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
personId: 1,
|
||||
name: "Alice",
|
||||
likedPosts: [
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "About airplanes",
|
||||
counters: {
|
||||
code: 2,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
likes: 4,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
));
|
||||
|
||||
loadedUser!.name = "Anna";
|
||||
loadedUser!.likedPosts = [post1];
|
||||
await connection.getRepository(User).persist(loadedUser!);
|
||||
|
||||
loadedUser = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPosts", "likedPost")
|
||||
.orderBy("likedPost.id")
|
||||
.where("user.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedUser!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
personId: 1,
|
||||
name: "Anna",
|
||||
likedPosts: [
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
code: 1,
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
));
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.counters.likedUser", "likedUser")
|
||||
.where("post.id = :id", { id: 2 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.counters.likedUser).to.be.empty;
|
||||
})));
|
||||
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,30 @@
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {JoinColumn} from "../../../../../src/decorator/relations/JoinColumn";
|
||||
import {ManyToOne} from "../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Embedded} from "../../../../../src/decorator/Embedded";
|
||||
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {User} from "./User";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
@ManyToOne(type => User)
|
||||
@JoinColumn()
|
||||
likedUser: User;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
import {Index} from "../../../../../src/decorator/Index";
|
||||
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "counters.code", "counters.subcounters.version"])
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@PrimaryColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,24 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {OneToMany} from "../../../../../src/decorator/relations/OneToMany";
|
||||
import {Index} from "../../../../../src/decorator/Index";
|
||||
import {PrimaryColumn} from "../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "personId"])
|
||||
export class User {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
personId: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToMany(type => Post, post => post.counters.likedUser)
|
||||
likedPosts: Post[];
|
||||
|
||||
}
|
||||
@ -216,7 +216,7 @@ describe("embedded > embedded-one-to-one", () => {
|
||||
user2.likedPost = post2;
|
||||
await connection.getRepository(User).persist(user2);
|
||||
|
||||
const loadedUsers = await connection.manager
|
||||
let loadedUsers = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPost", "likedPost")
|
||||
.orderBy("user.id")
|
||||
@ -263,7 +263,7 @@ describe("embedded > embedded-one-to-one", () => {
|
||||
}
|
||||
));
|
||||
|
||||
const loadedUser = await connection.manager
|
||||
let loadedUser = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPost", "likedPost")
|
||||
.where("user.id = :id", { id: 1 })
|
||||
@ -292,15 +292,16 @@ describe("embedded > embedded-one-to-one", () => {
|
||||
|
||||
loadedUser!.name = "Anna";
|
||||
loadedUser!.likedPost = post3;
|
||||
console.log(loadedUser);
|
||||
await connection.getRepository(User).persist(loadedUser!);
|
||||
|
||||
const loadedUser2 = await connection.manager
|
||||
loadedUser = await connection.manager
|
||||
.createQueryBuilder(User, "user")
|
||||
.leftJoinAndSelect("user.likedPost", "likedPost")
|
||||
.where("user.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedUser2!.should.be.eql(
|
||||
expect(loadedUser!.should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
name: "Anna",
|
||||
@ -321,11 +322,11 @@ describe("embedded > embedded-one-to-one", () => {
|
||||
}
|
||||
));
|
||||
|
||||
await connection.getRepository(User).remove(loadedUser2!);
|
||||
await connection.getRepository(User).remove(loadedUser!);
|
||||
|
||||
const loadedUsers2 = (await connection.getRepository(User).find())!;
|
||||
expect(loadedUsers2.length).to.be.equal(1);
|
||||
expect(loadedUsers2[0].name).to.be.equal("Bob");
|
||||
loadedUsers = (await connection.getRepository(User).find())!;
|
||||
expect(loadedUsers.length).to.be.equal(1);
|
||||
expect(loadedUsers[0].name).to.be.equal("Bob");
|
||||
})));
|
||||
});
|
||||
});
|
||||
|
||||
@ -0,0 +1,80 @@
|
||||
import "reflect-metadata";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Counters} from "./entity/Counters";
|
||||
import {Connection} from "../../../../src/connection/Connection";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../utils/test-utils";
|
||||
import {Subcounters} from "../embedded-many-to-one-case2/entity/Subcounters";
|
||||
|
||||
describe.skip("embedded > embedded-with-special-columns", () => {
|
||||
|
||||
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 insert, load, update and remove entities with embeddeds when embeds contains special columns (e.g. CreateDateColumn, UpdateDateColumn, VersionColumn", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.title = "About cars";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.comments = 1;
|
||||
post1.counters.favorites = 2;
|
||||
post1.counters.likes = 3;
|
||||
post1.counters.subcounters = new Subcounters();
|
||||
post1.counters.subcounters.watches = 5;
|
||||
await connection.getRepository(Post).persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.title = "About airplanes";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.comments = 2;
|
||||
post2.counters.favorites = 3;
|
||||
post2.counters.likes = 4;
|
||||
post2.counters.subcounters = new Subcounters();
|
||||
post2.counters.subcounters.watches = 10;
|
||||
await connection.getRepository(Post).persist(post2);
|
||||
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
console.log(loadedPosts);
|
||||
/*expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About cars",
|
||||
counters: {
|
||||
comments: 1,
|
||||
favorites: 2,
|
||||
likes: 3,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 5
|
||||
}
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About airplanes",
|
||||
counters: {
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
likes: 4,
|
||||
subcounters: {
|
||||
version: 1,
|
||||
watches: 10
|
||||
}
|
||||
}
|
||||
}
|
||||
));*/
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,27 @@
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../src/decorator/Embedded";
|
||||
import {CreateDateColumn} from "../../../../../src/decorator/columns/CreateDateColumn";
|
||||
import {UpdateDateColumn} from "../../../../../src/decorator/columns/UpdateDateColumn";
|
||||
import {Subcounters} from "./Subcounters";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@Embedded(() => Subcounters)
|
||||
subcounters: Subcounters;
|
||||
|
||||
@CreateDateColumn()
|
||||
createdDate: Date;
|
||||
|
||||
@UpdateDateColumn()
|
||||
updatedDate: Date;
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import {Entity} from "../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {Embedded} from "../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,12 @@
|
||||
import {Column} from "../../../../../src/decorator/columns/Column";
|
||||
import {VersionColumn} from "../../../../../src/decorator/columns/VersionColumn";
|
||||
|
||||
export class Subcounters {
|
||||
|
||||
@VersionColumn()
|
||||
version: number;
|
||||
|
||||
@Column()
|
||||
watches: number;
|
||||
|
||||
}
|
||||
@ -1,8 +1,12 @@
|
||||
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 {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Tag} from "./entity/Tag";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
@ -10,7 +14,7 @@ import {Image} from "./entity/Image";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
describe("query builder > relation-id > many-to-many > basic-functionality", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
@ -25,33 +29,33 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
|
||||
const tag = new Tag();
|
||||
tag.name = "kids";
|
||||
await connection.entityManager.persist(tag);
|
||||
await connection.manager.persist(tag);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "cars";
|
||||
await connection.entityManager.persist(category3);
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.categories = [category1, category2];
|
||||
post.tag = tag;
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about BMW";
|
||||
post2.categories = [category3];
|
||||
post2.tag = tag;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.tag", "tag")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
@ -67,7 +71,7 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
expect(loadedPosts![1].categories).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryIds).to.be.empty;
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.tag", "tag")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
@ -86,23 +90,23 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "kids";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "future";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about kids";
|
||||
post2.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.getMany();
|
||||
@ -114,7 +118,7 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
expect(loadedPosts![1].categoryIds[0]).to.be.equal(1);
|
||||
expect(loadedPosts![1].categoryIds[1]).to.be.equal(2);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
@ -135,16 +139,16 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
category2.name = "future";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(category1),
|
||||
connection.entityManager.persist(category2)
|
||||
connection.manager.persist(category1),
|
||||
connection.manager.persist(category2)
|
||||
]);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.subcategories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.subcategories")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
@ -160,7 +164,7 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
@ -171,11 +175,11 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
post2.categories = [category];
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(post1),
|
||||
connection.entityManager.persist(post2)
|
||||
connection.manager.persist(post1),
|
||||
connection.manager.persist(post2)
|
||||
]);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.where("category.id = :id", { id: category.id })
|
||||
@ -196,16 +200,16 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
category2.name = "future";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(category1),
|
||||
connection.entityManager.persist(category2)
|
||||
connection.manager.persist(category1),
|
||||
connection.manager.persist(category2)
|
||||
]);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "categories", qb => qb.andWhere("categories.id = :categoryId", { categoryId: 1 }))
|
||||
.getOne();
|
||||
@ -225,16 +229,16 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
category2.name = "future";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(category1),
|
||||
connection.entityManager.persist(category2)
|
||||
connection.manager.persist(category1),
|
||||
connection.manager.persist(category2)
|
||||
]);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.subcategories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.subcategories", "subCategories", qb => qb.andWhere("subCategories.id = :categoryId", { categoryId: 1 }))
|
||||
.getOne();
|
||||
@ -249,7 +253,7 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
@ -260,11 +264,11 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
post2.categories = [category];
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(post1),
|
||||
connection.entityManager.persist(post2)
|
||||
connection.manager.persist(post1),
|
||||
connection.manager.persist(post2)
|
||||
]);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "posts", qb => qb.andWhere("posts.id = :postId", { postId: 1 }))
|
||||
.where("category.id = :id", { id: category.id })
|
||||
@ -285,25 +289,25 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
image2.name = "photo2";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(image1),
|
||||
connection.entityManager.persist(image2)
|
||||
connection.manager.persist(image1),
|
||||
connection.manager.persist(image2)
|
||||
]);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
@ -333,25 +337,25 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
image2.name = "photo2";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(image1),
|
||||
connection.entityManager.persist(image2)
|
||||
connection.manager.persist(image1),
|
||||
connection.manager.persist(image2)
|
||||
]);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1, category2];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "categories2", qb => qb.andWhere("categories2.id = :categoryId", { categoryId: 1 }))
|
||||
@ -379,21 +383,21 @@ describe("query builder > load-relation-id-and-map > many-to-many", () => {
|
||||
image2.name = "photo2";
|
||||
|
||||
await Promise.all([
|
||||
connection.entityManager.persist(image1),
|
||||
connection.entityManager.persist(image2)
|
||||
connection.manager.persist(image1),
|
||||
connection.manager.persist(image2)
|
||||
]);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about BMW";
|
||||
post.categories = [category1];
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.leftJoinAndSelect("post.categories", "categories", "categories.id = :categoryId")
|
||||
.loadRelationIdAndMap("categories.imageIds", "categories.images")
|
||||
@ -0,0 +1,29 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Post} from "./Post";
|
||||
import {Image} from "./Image";
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.categories)
|
||||
posts: Post[];
|
||||
|
||||
@ManyToMany(type => Image)
|
||||
@JoinTable()
|
||||
images: Image[];
|
||||
|
||||
imageIds: number[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Image {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,34 @@
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Category} from "./Category";
|
||||
import {Tag} from "./Tag";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@ManyToOne(type => Tag)
|
||||
tag: Tag;
|
||||
|
||||
tagId: number;
|
||||
|
||||
@ManyToMany(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
@ManyToMany(type => Category)
|
||||
@JoinTable()
|
||||
subcategories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,14 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Tag {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -0,0 +1,96 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Counters} from "./entity/Counters";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > many-to-many > embedded", () => {
|
||||
|
||||
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 ids when RelationId decorator used in embedded table", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "About BMW";
|
||||
post1.counters = new Counters();
|
||||
post1.counters.likes = 1;
|
||||
post1.counters.comments = 2;
|
||||
post1.counters.favorites = 3;
|
||||
post1.counters.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "About Boeing";
|
||||
post2.counters = new Counters();
|
||||
post2.counters.likes = 3;
|
||||
post2.counters.comments = 4;
|
||||
post2.counters.favorites = 5;
|
||||
post2.counters.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.counters.categoryIds", "post.counters.categories")
|
||||
.orderBy("post.id")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].should.be.eql(
|
||||
{
|
||||
id: 1,
|
||||
title: "About BMW",
|
||||
counters: {
|
||||
likes: 1,
|
||||
comments: 2,
|
||||
favorites: 3,
|
||||
categoryIds: [1, 2]
|
||||
}
|
||||
}
|
||||
));
|
||||
expect(loadedPosts[1].should.be.eql(
|
||||
{
|
||||
id: 2,
|
||||
title: "About Boeing",
|
||||
counters: {
|
||||
likes: 3,
|
||||
comments: 4,
|
||||
favorites: 5,
|
||||
categoryIds: [3, 4]
|
||||
}
|
||||
}
|
||||
));
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.counters.categories)
|
||||
posts: Post[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,23 @@
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Category} from "./Category";
|
||||
|
||||
export class Counters {
|
||||
|
||||
@Column()
|
||||
likes: number;
|
||||
|
||||
@Column()
|
||||
comments: number;
|
||||
|
||||
@Column()
|
||||
favorites: number;
|
||||
|
||||
@ManyToMany(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,19 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Embedded} from "../../../../../../../src/decorator/Embedded";
|
||||
import {Counters} from "./Counters";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Embedded(() => Counters)
|
||||
counters: Counters;
|
||||
|
||||
}
|
||||
@ -0,0 +1,37 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Post} from "./Post";
|
||||
import {Image} from "./Image";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "code"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
isRemoved: boolean = false;
|
||||
|
||||
@ManyToMany(type => Post, post => post.categories)
|
||||
posts: Post[];
|
||||
|
||||
@ManyToMany(type => Image, image => image.categories)
|
||||
@JoinTable()
|
||||
images: Image[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
imageIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
export class Image {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Category, category => category.images)
|
||||
categories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
import {ManyToMany} from "../../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {JoinTable} from "../../../../../../../src/decorator/relations/JoinTable";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "authorId"])
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
authorId: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@Column()
|
||||
isRemoved: boolean = false;
|
||||
|
||||
@ManyToMany(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
@ManyToMany(type => Category)
|
||||
@JoinTable()
|
||||
subcategories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,731 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Image} from "./entity/Image";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > relation-id > many-to-many > multiple-pk", () => {
|
||||
|
||||
let connections: Connection[];
|
||||
before(async () => connections = await createTestingConnections({
|
||||
entities: [__dirname + "/entity/*{.js,.ts}"],
|
||||
schemaCreate: true,
|
||||
dropSchemaOnConnection: true,
|
||||
}));
|
||||
beforeEach(() => reloadTestingDatabases(connections));
|
||||
after(() => closeTestingConnections(connections));
|
||||
|
||||
describe("owner side", () => {
|
||||
|
||||
it("should load ids when both entities have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 2;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 1;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.code = 2;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Boeing";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 3, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.eql({ id: 4, code: 2 });
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.authorId = :authorId", { authorId: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPost!.categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when only one entity have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "Image #2";
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const image3 = new Image();
|
||||
image3.name = "Image #3";
|
||||
await connection.manager.persist(image3);
|
||||
|
||||
const image4 = new Image();
|
||||
image4.name = "Image #4";
|
||||
await connection.manager.persist(image4);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 2;
|
||||
category2.name = "airplanes";
|
||||
category2.images = [image3, image4];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].imageIds[0]).to.be.equal(1);
|
||||
expect(loadedCategories[0].imageIds[1]).to.be.equal(2);
|
||||
expect(loadedCategories[1].imageIds).to.not.be.empty;
|
||||
expect(loadedCategories[1].imageIds[0]).to.be.equal(3);
|
||||
expect(loadedCategories[1].imageIds[1]).to.be.equal(4);
|
||||
|
||||
const loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.andWhere("category.code = :code", { code: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.imageIds).to.not.be.empty;
|
||||
expect(loadedCategory!.imageIds[0]).to.be.equal(1);
|
||||
expect(loadedCategory!.imageIds[1]).to.be.equal(2);
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when both entities have multiple primary keys and additional condition used", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.isRemoved = true;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 1;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.code = 2;
|
||||
category4.isRemoved = true;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Boeing";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.id = :id AND category.code = :code", { id: 1, code: 1 }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds).to.be.empty;
|
||||
|
||||
loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.code = :code", { code: 1 }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 3, code: 1 });
|
||||
|
||||
loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.isRemoved = :isRemoved", { isRemoved: true }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 4, code: 2 });
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.isRemoved = :isRemoved", { isRemoved: true }))
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.authorId = :authorId", { authorId: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds[0]).to.be.eql({ id: 2, code: 1 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when both entities have multiple primary keys and related entity does not have inverse side", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 2;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 1;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.code = 2;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.subcategories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Boeing";
|
||||
post2.subcategories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.subcategories")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 3, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.eql({ id: 4, code: 2 });
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.subcategories")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.authorId = :authorId", { authorId: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPost!.categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on nested relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "Image #2";
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const image3 = new Image();
|
||||
image3.name = "Image #3";
|
||||
await connection.manager.persist(image3);
|
||||
|
||||
const image4 = new Image();
|
||||
image4.name = "Image #4";
|
||||
await connection.manager.persist(image4);
|
||||
|
||||
const image5 = new Image();
|
||||
image5.name = "Image #5";
|
||||
await connection.manager.persist(image5);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2, image3];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.name = "airplanes";
|
||||
category2.images = [image4, image5];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 2;
|
||||
category3.name = "Boeing";
|
||||
category3.images = [image5];
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.categories = [category1];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Boeing";
|
||||
post2.categories = [category2, category3];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.leftJoinAndSelect("post.categories", "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds.length).to.be.equal(1);
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[0].categories).to.not.be.empty;
|
||||
expect(loadedPosts[0].categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categories[0].imageIds.length).to.be.equal(3);
|
||||
expect(loadedPosts[0].categories[0].imageIds[0]).to.be.equal(1);
|
||||
expect(loadedPosts[0].categories[0].imageIds[1]).to.be.equal(2);
|
||||
expect(loadedPosts[0].categories[0].imageIds[2]).to.be.equal(3);
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.eql({ id: 3, code: 2 });
|
||||
expect(loadedPosts[1].categories).to.not.be.empty;
|
||||
expect(loadedPosts[1].categories.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categories[0].imageIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categories[0].imageIds[0]).to.be.equal(4);
|
||||
expect(loadedPosts[1].categories[0].imageIds[1]).to.be.equal(5);
|
||||
expect(loadedPosts[1].categories[1].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categories[1].imageIds.length).to.be.equal(1);
|
||||
expect(loadedPosts[1].categories[1].imageIds[0]).to.be.equal(5);
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.leftJoinAndSelect("post.categories", "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.authorId = :authorId", { authorId: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPost!.categories).to.not.be.empty;
|
||||
expect(loadedPost!.categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPost!.categories[0].imageIds.length).to.be.equal(3);
|
||||
expect(loadedPost!.categories[0].imageIds[0]).to.be.equal(1);
|
||||
expect(loadedPost!.categories[0].imageIds[1]).to.be.equal(2);
|
||||
expect(loadedPost!.categories[0].imageIds[2]).to.be.equal(3);
|
||||
|
||||
})));
|
||||
});
|
||||
|
||||
describe("inverse side", () => {
|
||||
|
||||
it("should load ids when both entities have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 2;
|
||||
post2.title = "About Audi";
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.id = 3;
|
||||
post3.authorId = 1;
|
||||
post3.title = "About Boeing";
|
||||
await connection.manager.persist(post3);
|
||||
|
||||
const post4 = new Post();
|
||||
post4.id = 4;
|
||||
post4.authorId = 2;
|
||||
post4.title = "About Airbus";
|
||||
await connection.manager.persist(post4);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
category1.posts = [post1, post2];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.name = "airplanes";
|
||||
category2.posts = [post3, post4];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedCategories[0].postIds[1]).to.be.eql({ id: 2, authorId: 2 });
|
||||
expect(loadedCategories[1].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[1].postIds[0]).to.be.eql({ id: 3, authorId: 1 });
|
||||
expect(loadedCategories[1].postIds[1]).to.be.eql({ id: 4, authorId: 2 });
|
||||
|
||||
const loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.andWhere("category.code = :code", { code: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.postIds).to.not.be.empty;
|
||||
expect(loadedCategory!.postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedCategory!.postIds[1]).to.be.eql({ id: 2, authorId: 2 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when only one entity have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "category #1";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.name = "category #2";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 2;
|
||||
category3.name = "category #3";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.code = 2;
|
||||
category4.name = "category #4";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
image1.categories = [category1, category2];
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "Image #2";
|
||||
image2.categories = [category3, category4];
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const loadedImages = await connection.manager
|
||||
.createQueryBuilder(Image, "image")
|
||||
.loadRelationIdAndMap("image.categoryIds", "image.categories")
|
||||
.getMany();
|
||||
|
||||
expect(loadedImages[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedImages[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedImages[0].categoryIds[1]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedImages[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedImages[1].categoryIds[0]).to.be.eql({ id: 3, code: 2 });
|
||||
expect(loadedImages[1].categoryIds[1]).to.be.eql({ id: 4, code: 2 });
|
||||
|
||||
const loadedImage = await connection.manager
|
||||
.createQueryBuilder(Image, "image")
|
||||
.loadRelationIdAndMap("image.categoryIds", "image.categories")
|
||||
.where("image.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedImage!.categoryIds).to.not.be.empty;
|
||||
expect(loadedImage!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedImage!.categoryIds[1]).to.be.eql({ id: 2, code: 1 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when both entities have multiple primary keys and additional condition used", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.isRemoved = true;
|
||||
post2.title = "About Audi";
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.id = 3;
|
||||
post3.authorId = 1;
|
||||
post3.title = "About Boeing";
|
||||
await connection.manager.persist(post3);
|
||||
|
||||
const post4 = new Post();
|
||||
post4.id = 4;
|
||||
post4.authorId = 2;
|
||||
post4.isRemoved = true;
|
||||
post4.title = "About Airbus";
|
||||
await connection.manager.persist(post4);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
category1.posts = [post1, post2];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.name = "airplanes";
|
||||
category2.posts = [post3, post4];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
let loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "post", qb => qb.andWhere("post.id = :id AND post.authorId = :authorId", { id: 1, authorId: 1 }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedCategories[1].postIds).to.be.empty;
|
||||
|
||||
loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "post", qb => qb.andWhere("post.authorId = :authorId", { authorId: 1 }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedCategories[0].postIds[1]).to.be.eql({ id: 2, authorId: 1 });
|
||||
expect(loadedCategories[1].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[1].postIds[0]).to.be.eql({ id: 3, authorId: 1 });
|
||||
|
||||
loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "post", qb => qb.andWhere("post.isRemoved = :isRemoved", { isRemoved: true }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedCategories[0].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[0].postIds[0]).to.be.eql({ id: 2, authorId: 1 });
|
||||
expect(loadedCategories[1].postIds).to.not.be.empty;
|
||||
expect(loadedCategories[1].postIds[0]).to.be.eql({ id: 4, authorId: 2 });
|
||||
|
||||
const loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "post", qb => qb.andWhere("post.isRemoved = :isRemoved", { isRemoved: true }))
|
||||
.where("category.id = :id", { id: 1 })
|
||||
.andWhere("category.code = :code", { code: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.postIds).to.not.be.empty;
|
||||
expect(loadedCategory!.postIds[0]).to.be.eql({ id: 2, authorId: 1 });
|
||||
|
||||
})));
|
||||
|
||||
it("should load ids when loadRelationIdAndMap used on nested relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Audi";
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const post3 = new Post();
|
||||
post3.id = 3;
|
||||
post3.authorId = 1;
|
||||
post3.title = "About Boeing";
|
||||
await connection.manager.persist(post3);
|
||||
|
||||
const post4 = new Post();
|
||||
post4.id = 4;
|
||||
post4.authorId = 2;
|
||||
post4.title = "About Airbus";
|
||||
await connection.manager.persist(post4);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
category1.posts = [post1, post2];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 1;
|
||||
category2.name = "BMW";
|
||||
category2.posts = [post1];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 2;
|
||||
category3.name = "airplanes";
|
||||
category3.posts = [post3, post4];
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
image1.categories = [category1, category2];
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "Image #2";
|
||||
image2.categories = [category3];
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const loadedImages = await connection.manager
|
||||
.createQueryBuilder(Image, "image")
|
||||
.loadRelationIdAndMap("image.categoryIds", "image.categories")
|
||||
.leftJoinAndSelect("image.categories", "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.getMany();
|
||||
|
||||
expect(loadedImages[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedImages[0].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedImages[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedImages[0].categoryIds[1]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedImages[0].categories).to.not.be.empty;
|
||||
expect(loadedImages[0].categories.length).to.be.equal(2);
|
||||
expect(loadedImages[0].categories[0].postIds).to.not.be.empty;
|
||||
expect(loadedImages[0].categories[0].postIds.length).to.be.equal(2);
|
||||
expect(loadedImages[0].categories[0].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedImages[0].categories[0].postIds[1]).to.be.eql({ id: 2, authorId: 1 });
|
||||
expect(loadedImages[0].categories[1].postIds).to.not.be.empty;
|
||||
expect(loadedImages[0].categories[1].postIds.length).to.be.equal(1);
|
||||
expect(loadedImages[0].categories[1].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedImages[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedImages[1].categoryIds.length).to.be.equal(1);
|
||||
expect(loadedImages[1].categoryIds[0]).to.be.eql({ id: 3, code: 2 });
|
||||
expect(loadedImages[1].categories).to.not.be.empty;
|
||||
expect(loadedImages[1].categories[0].postIds).to.not.be.empty;
|
||||
expect(loadedImages[1].categories[0].postIds.length).to.be.equal(2);
|
||||
expect(loadedImages[1].categories[0].postIds[0]).to.be.eql({ id: 3, authorId: 1 });
|
||||
expect(loadedImages[1].categories[0].postIds[1]).to.be.eql({ id: 4, authorId: 2 });
|
||||
|
||||
const loadedImage = await connection.manager
|
||||
.createQueryBuilder(Image, "image")
|
||||
.loadRelationIdAndMap("image.categoryIds", "image.categories")
|
||||
.leftJoinAndSelect("image.categories", "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.where("image.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedImage!.categoryIds).to.not.be.empty;
|
||||
expect(loadedImage!.categoryIds.length).to.be.equal(2);
|
||||
expect(loadedImage!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedImage!.categoryIds[1]).to.be.eql({ id: 2, code: 1 });
|
||||
expect(loadedImage!.categories).to.not.be.empty;
|
||||
expect(loadedImage!.categories.length).to.be.equal(2);
|
||||
expect(loadedImage!.categories[0].postIds).to.not.be.empty;
|
||||
expect(loadedImage!.categories[0].postIds.length).to.be.equal(2);
|
||||
expect(loadedImage!.categories[0].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
expect(loadedImage!.categories[0].postIds[1]).to.be.eql({ id: 2, authorId: 1 });
|
||||
expect(loadedImage!.categories[1].postIds).to.not.be.empty;
|
||||
expect(loadedImage!.categories[1].postIds.length).to.be.equal(1);
|
||||
expect(loadedImage!.categories[1].postIds[0]).to.be.eql({ id: 1, authorId: 1 });
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
@ -0,0 +1,240 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
reloadTestingDatabases
|
||||
} from "../../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../../src/connection/Connection";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Image} from "./entity/Image";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe.only("query builder > load-relation-id-and-map > one-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));
|
||||
|
||||
it("should load id when loadRelationIdAndMap used with OneToMany relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.equal(1);
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.equal(2);
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.equal(3);
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.equal(4);
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPost!.categoryIds[0]).to.be.equal(1);
|
||||
expect(loadedPost!.categoryIds[1]).to.be.equal(2);
|
||||
})));
|
||||
|
||||
it("should load id when loadRelationIdAndMap used with additional condition", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
category2.isRemoved = true;
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.name = "Boeing";
|
||||
category4.isRemoved = true;
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.isRemoved = :isRemoved", { isRemoved: true }))
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds.length).to.be.equal(1);
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.equal(2);
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds.length).to.be.equal(1);
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.equal(4);
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories", "category", qb => qb.andWhere("category.id = :categoryId", { categoryId: 1 }))
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds.length).to.be.equal(1);
|
||||
expect(loadedPost!.categoryIds[0]).to.be.equal(1);
|
||||
})));
|
||||
|
||||
it("should load id when loadRelationIdAndMap used on nested relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const image1 = new Image();
|
||||
image1.name = "Image #1";
|
||||
await connection.manager.persist(image1);
|
||||
|
||||
const image2 = new Image();
|
||||
image2.name = "Image #2";
|
||||
await connection.manager.persist(image2);
|
||||
|
||||
const image3 = new Image();
|
||||
image3.name = "Image #3";
|
||||
await connection.manager.persist(image3);
|
||||
|
||||
const image4 = new Image();
|
||||
image4.name = "Image #4";
|
||||
await connection.manager.persist(image4);
|
||||
|
||||
const image5 = new Image();
|
||||
image5.name = "Image #5";
|
||||
await connection.manager.persist(image5);
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
category1.images = [image1, image2];
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "BMW";
|
||||
category2.images = [image3];
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.name = "airplanes";
|
||||
category3.images = [image4, image5];
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.leftJoinAndSelect("post.categories", "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.equal(1);
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.equal(2);
|
||||
expect(loadedPosts[0].categories).to.not.be.empty;
|
||||
expect(loadedPosts[0].categories.length).to.be.equal(2);
|
||||
expect(loadedPosts[0].categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categories[0].imageIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[0].categories[0].imageIds[0]).to.be.equal(1);
|
||||
expect(loadedPosts[0].categories[0].imageIds[1]).to.be.equal(2);
|
||||
expect(loadedPosts[0].categories[1].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categories[1].imageIds.length).to.be.equal(1);
|
||||
expect(loadedPosts[0].categories[1].imageIds[0]).to.be.equal(3);
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.equal(3);
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.equal(4);
|
||||
expect(loadedPosts[1].categories).to.not.be.empty;
|
||||
expect(loadedPosts[1].categories.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categories[0].imageIds.length).to.be.equal(2);
|
||||
expect(loadedPosts[1].categories[0].imageIds[0]).to.be.equal(4);
|
||||
expect(loadedPosts[1].categories[0].imageIds[1]).to.be.equal(5);
|
||||
expect(loadedPosts[1].categories[1].imageIds).to.be.empty;
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.leftJoinAndSelect("post.categories", "category")
|
||||
.loadRelationIdAndMap("category.imageIds", "category.images")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds.length).to.be.equal(2);
|
||||
expect(loadedPost!.categoryIds[0]).to.be.equal(1);
|
||||
expect(loadedPost!.categoryIds[1]).to.be.equal(2);
|
||||
expect(loadedPost!.categories).to.not.be.empty;
|
||||
expect(loadedPost!.categories.length).to.be.equal(2);
|
||||
expect(loadedPost!.categories[0].imageIds).to.not.be.empty;
|
||||
expect(loadedPost!.categories[0].imageIds.length).to.be.equal(2);
|
||||
expect(loadedPost!.categories[0].imageIds[0]).to.be.equal(1);
|
||||
expect(loadedPost!.categories[0].imageIds[1]).to.be.equal(2);
|
||||
expect(loadedPost!.categories[1].imageIds).to.not.be.empty;
|
||||
expect(loadedPost!.categories[1].imageIds.length).to.be.equal(1);
|
||||
expect(loadedPost!.categories[1].imageIds[0]).to.be.equal(3);
|
||||
})));
|
||||
|
||||
});
|
||||
@ -0,0 +1,31 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Image} from "./Image";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@Column()
|
||||
isRemoved: boolean = false;
|
||||
|
||||
@OneToMany(type => Image, image => image.category)
|
||||
images: Image[];
|
||||
|
||||
imageIds: number[];
|
||||
|
||||
@ManyToOne(type => Post, post => post.categories)
|
||||
post: Post;
|
||||
|
||||
postId: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
export class Image {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToOne(type => Category, category => category.images)
|
||||
category: Category;
|
||||
|
||||
categoryId: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,21 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@OneToMany(type => Category, category => category.post)
|
||||
categories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Post} from "./Post";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {ManyToOne} from "../../../../../../../src/decorator/relations/ManyToOne";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "code"])
|
||||
export class Category {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
code: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToOne(type => Post, post => post.categories)
|
||||
post: Post;
|
||||
|
||||
postId: number;
|
||||
|
||||
}
|
||||
@ -0,0 +1,26 @@
|
||||
import {Entity} from "../../../../../../../src/decorator/entity/Entity";
|
||||
import {Column} from "../../../../../../../src/decorator/columns/Column";
|
||||
import {Index} from "../../../../../../../src/decorator/Index";
|
||||
import {PrimaryColumn} from "../../../../../../../src/decorator/columns/PrimaryColumn";
|
||||
import {Category} from "./Category";
|
||||
import {OneToMany} from "../../../../../../../src/decorator/relations/OneToMany";
|
||||
|
||||
@Entity()
|
||||
@Index(["id", "authorId"])
|
||||
export class Post {
|
||||
|
||||
@PrimaryColumn()
|
||||
id: number;
|
||||
|
||||
@PrimaryColumn()
|
||||
authorId: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@OneToMany(type => Category, category => category.post)
|
||||
categories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -0,0 +1,91 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {
|
||||
closeTestingConnections,
|
||||
createTestingConnections,
|
||||
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("query builder > relation-id > one-to-many > multiple-pk", () => {
|
||||
|
||||
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 ids when both entities have multiple primary keys", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.id = 1;
|
||||
category1.code = 1;
|
||||
category1.name = "cars";
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.id = 2;
|
||||
category2.code = 2;
|
||||
category2.name = "BMW";
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const category3 = new Category();
|
||||
category3.id = 3;
|
||||
category3.code = 1;
|
||||
category3.name = "airplanes";
|
||||
await connection.manager.persist(category3);
|
||||
|
||||
const category4 = new Category();
|
||||
category4.id = 4;
|
||||
category4.code = 2;
|
||||
category4.name = "Boeing";
|
||||
await connection.manager.persist(category4);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.id = 1;
|
||||
post1.authorId = 1;
|
||||
post1.title = "About BMW";
|
||||
post1.categories = [category1, category2];
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.id = 2;
|
||||
post2.authorId = 1;
|
||||
post2.title = "About Boeing";
|
||||
post2.categories = [category3, category4];
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
const loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.getMany();
|
||||
|
||||
expect(loadedPosts[0].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[0].categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPosts[0].categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
expect(loadedPosts[1].categoryIds).to.not.be.empty;
|
||||
expect(loadedPosts[1].categoryIds[0]).to.be.eql({ id: 3, code: 1 });
|
||||
expect(loadedPosts[1].categoryIds[1]).to.be.eql({ id: 4, code: 2 });
|
||||
|
||||
const loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryIds", "post.categories")
|
||||
.where("post.id = :id", { id: 1 })
|
||||
.andWhere("post.authorId = :authorId", { authorId: 1 })
|
||||
.getOne();
|
||||
|
||||
expect(loadedPost!.categoryIds).to.not.be.empty;
|
||||
expect(loadedPost!.categoryIds[0]).to.be.eql({ id: 1, code: 1 });
|
||||
expect(loadedPost!.categoryIds[1]).to.be.eql({ id: 2, code: 2 });
|
||||
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,29 +0,0 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToMany} from "../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {JoinTable} from "../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Post} from "./Post";
|
||||
import {Image} from "./Image";
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@ManyToMany(type => Post, post => post.categories)
|
||||
posts: Post[];
|
||||
|
||||
@ManyToMany(type => Image)
|
||||
@JoinTable()
|
||||
images: Image[];
|
||||
|
||||
imageIds: number[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Image {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -1,34 +0,0 @@
|
||||
import {ManyToMany} from "../../../../../../src/decorator/relations/ManyToMany";
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {JoinTable} from "../../../../../../src/decorator/relations/JoinTable";
|
||||
import {Category} from "./Category";
|
||||
import {Tag} from "./Tag";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@ManyToOne(type => Tag)
|
||||
tag: Tag;
|
||||
|
||||
tagId: number;
|
||||
|
||||
@ManyToMany(type => Category, category => category.posts)
|
||||
@JoinTable()
|
||||
categories: Category[];
|
||||
|
||||
@ManyToMany(type => Category)
|
||||
@JoinTable()
|
||||
subcategories: Category[];
|
||||
|
||||
categoryIds: number[];
|
||||
|
||||
}
|
||||
@ -1,14 +0,0 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
|
||||
@Entity()
|
||||
export class Tag {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Post} from "./entity/Post";
|
||||
import {Category} from "./entity/Category";
|
||||
@ -25,33 +25,33 @@ describe("query builder > load-relation-id-and-map > many-to-one", () => {
|
||||
|
||||
const category1 = new Category();
|
||||
category1.name = "cars";
|
||||
await connection.entityManager.persist(category1);
|
||||
await connection.manager.persist(category1);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "airplanes";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const categoryByName1 = new Category();
|
||||
categoryByName1.name = "BMW";
|
||||
await connection.entityManager.persist(categoryByName1);
|
||||
await connection.manager.persist(categoryByName1);
|
||||
|
||||
const categoryByName2 = new Category();
|
||||
categoryByName2.name = "Boeing";
|
||||
await connection.entityManager.persist(categoryByName2);
|
||||
await connection.manager.persist(categoryByName2);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BWM";
|
||||
post1.category = category1;
|
||||
post1.categoryByName = categoryByName1;
|
||||
await connection.entityManager.persist(post1);
|
||||
await connection.manager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Boeing";
|
||||
post2.category = category2;
|
||||
post2.categoryByName = categoryByName2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryId", "post.category")
|
||||
.loadRelationIdAndMap("post.categoryName", "post.categoryByName")
|
||||
@ -66,7 +66,7 @@ describe("query builder > load-relation-id-and-map > many-to-one", () => {
|
||||
expect(loadedPosts![1].categoryName).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryName).to.be.equal("Boeing");
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryId", "post.category")
|
||||
.loadRelationIdAndMap("post.categoryName", "post.categoryByName")
|
||||
@ -83,18 +83,18 @@ describe("query builder > load-relation-id-and-map > many-to-one", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about cars";
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const postCategory = new PostCategory();
|
||||
postCategory.category = category;
|
||||
postCategory.post = post;
|
||||
await connection.entityManager.persist(postCategory);
|
||||
await connection.manager.persist(postCategory);
|
||||
|
||||
let loadedPostCategory = await connection.entityManager
|
||||
let loadedPostCategory = await connection.manager
|
||||
.createQueryBuilder(PostCategory, "postCategory")
|
||||
.loadRelationIdAndMap("postCategory.postId", "postCategory.post")
|
||||
.loadRelationIdAndMap("postCategory.categoryId", "postCategory.category")
|
||||
@ -110,23 +110,23 @@ describe("query builder > load-relation-id-and-map > many-to-one", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about cars";
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const image = new Image();
|
||||
image.name = "image #1";
|
||||
await connection.entityManager.persist(image);
|
||||
await connection.manager.persist(image);
|
||||
|
||||
const postCategory = new PostCategory();
|
||||
postCategory.category = category;
|
||||
postCategory.post = post;
|
||||
postCategory.image = image;
|
||||
await connection.entityManager.persist(postCategory);
|
||||
await connection.manager.persist(postCategory);
|
||||
|
||||
let loadedPostCategory = await connection.entityManager
|
||||
let loadedPostCategory = await connection.manager
|
||||
.createQueryBuilder(PostCategory, "postCategory")
|
||||
.loadRelationIdAndMap("postCategory.imageId", "postCategory.image")
|
||||
.getOne();
|
||||
|
||||
@ -1,21 +0,0 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {OneToMany} from "../../../../../../src/decorator/relations/OneToMany";
|
||||
import {Post} from "./Post";
|
||||
|
||||
@Entity()
|
||||
export class Category {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
name: string;
|
||||
|
||||
@OneToMany(type => Post, post => post.category)
|
||||
posts: Post[];
|
||||
|
||||
postIds: number[];
|
||||
|
||||
}
|
||||
@ -1,21 +0,0 @@
|
||||
import {Entity} from "../../../../../../src/decorator/entity/Entity";
|
||||
import {PrimaryGeneratedColumn} from "../../../../../../src/decorator/columns/PrimaryGeneratedColumn";
|
||||
import {Column} from "../../../../../../src/decorator/columns/Column";
|
||||
import {ManyToOne} from "../../../../../../src/decorator/relations/ManyToOne";
|
||||
import {Category} from "./Category";
|
||||
|
||||
@Entity()
|
||||
export class Post {
|
||||
|
||||
@PrimaryGeneratedColumn()
|
||||
id: number;
|
||||
|
||||
@Column()
|
||||
title: string;
|
||||
|
||||
@ManyToOne(type => Category, category => category.posts)
|
||||
category: Category;
|
||||
|
||||
categoryId: number;
|
||||
|
||||
}
|
||||
@ -1,75 +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 {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
|
||||
const should = chai.should();
|
||||
|
||||
describe("query builder > load-relation-id-and-map > one-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));
|
||||
|
||||
it("should load id when loadRelationIdAndMap used with OneToMany relation", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category = category;
|
||||
await connection.entityManager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.category = category;
|
||||
await connection.entityManager.persist(post2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts")
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.postIds).to.not.be.empty;
|
||||
expect(loadedCategory!.postIds.length).to.be.equal(2);
|
||||
expect(loadedCategory!.postIds[0]).to.be.equal(1);
|
||||
expect(loadedCategory!.postIds[1]).to.be.equal(2);
|
||||
})));
|
||||
|
||||
it("should load id when loadRelationIdAndMap used with OneToMany relation and additional condition", () => Promise.all(connections.map(async connection => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "cars";
|
||||
await connection.entityManager.persist(category);
|
||||
|
||||
const post1 = new Post();
|
||||
post1.title = "about BMW";
|
||||
post1.category = category;
|
||||
await connection.entityManager.persist(post1);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about Audi";
|
||||
post2.category = category;
|
||||
await connection.entityManager.persist(post2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postIds", "category.posts", "posts", qb => qb.andWhere("posts.id = :postId", { postId: 1 }))
|
||||
.getOne();
|
||||
|
||||
expect(loadedCategory!.postIds).to.not.be.empty;
|
||||
expect(loadedCategory!.postIds.length).to.be.equal(1);
|
||||
expect(loadedCategory!.postIds[0]).to.be.equal(1);
|
||||
})));
|
||||
|
||||
});
|
||||
@ -1,7 +1,7 @@
|
||||
import "reflect-metadata";
|
||||
import * as chai from "chai";
|
||||
import {expect} from "chai";
|
||||
import {createTestingConnections, closeTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {closeTestingConnections, createTestingConnections, reloadTestingDatabases} from "../../../../utils/test-utils";
|
||||
import {Connection} from "../../../../../src/connection/Connection";
|
||||
import {Category} from "./entity/Category";
|
||||
import {Post} from "./entity/Post";
|
||||
@ -24,23 +24,23 @@ describe("query builder > load-relation-id-and-map > one-to-one", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "kids";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.category = category;
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "cars";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about cars";
|
||||
post2.category = category2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedPosts = await connection.entityManager
|
||||
let loadedPosts = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryId", "post.category")
|
||||
.getMany();
|
||||
@ -50,7 +50,7 @@ describe("query builder > load-relation-id-and-map > one-to-one", () => {
|
||||
expect(loadedPosts![1].categoryId).to.not.be.empty;
|
||||
expect(loadedPosts![1].categoryId).to.be.equal(2);
|
||||
|
||||
let loadedPost = await connection.entityManager
|
||||
let loadedPost = await connection.manager
|
||||
.createQueryBuilder(Post, "post")
|
||||
.loadRelationIdAndMap("post.categoryId", "post.category")
|
||||
.where("post.id = :id", { id: post.id })
|
||||
@ -64,23 +64,23 @@ describe("query builder > load-relation-id-and-map > one-to-one", () => {
|
||||
|
||||
const category = new Category();
|
||||
category.name = "kids";
|
||||
await connection.entityManager.persist(category);
|
||||
await connection.manager.persist(category);
|
||||
|
||||
const post = new Post();
|
||||
post.title = "about kids";
|
||||
post.category2 = category;
|
||||
await connection.entityManager.persist(post);
|
||||
await connection.manager.persist(post);
|
||||
|
||||
const category2 = new Category();
|
||||
category2.name = "cars";
|
||||
await connection.entityManager.persist(category2);
|
||||
await connection.manager.persist(category2);
|
||||
|
||||
const post2 = new Post();
|
||||
post2.title = "about cars";
|
||||
post2.category2 = category2;
|
||||
await connection.entityManager.persist(post2);
|
||||
await connection.manager.persist(post2);
|
||||
|
||||
let loadedCategories = await connection.entityManager
|
||||
let loadedCategories = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postId", "category.post")
|
||||
.getMany();
|
||||
@ -90,7 +90,7 @@ describe("query builder > load-relation-id-and-map > one-to-one", () => {
|
||||
expect(loadedCategories![1].postId).to.not.be.empty;
|
||||
expect(loadedCategories![1].postId).to.be.equal(2);
|
||||
|
||||
let loadedCategory = await connection.entityManager
|
||||
let loadedCategory = await connection.manager
|
||||
.createQueryBuilder(Category, "category")
|
||||
.loadRelationIdAndMap("category.postId", "category.post")
|
||||
.getOne();
|
||||
|
||||
@ -191,4 +191,17 @@ export function setupConnection(callback: (connection: Connection) => any, entit
|
||||
return connection;
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates random text array with custom length.
|
||||
*/
|
||||
export function generateRandomText(length: number): string {
|
||||
let text = "";
|
||||
const characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||
|
||||
for(let i = 0; i <= length; i++ )
|
||||
text += characters.charAt(Math.floor(Math.random() * characters.length));
|
||||
|
||||
return text;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user