new way of converting raw db results to object

This commit is contained in:
Umed Khudoiberdiev 2016-02-21 22:38:16 +05:00
parent 7d34424eec
commit d01d2b6cea
12 changed files with 287 additions and 129 deletions

View File

@ -43,6 +43,7 @@
},
"dependencies": {
"fs": "^0.0.2",
"lodash": "^4.5.0",
"mongodb": ">=2.0.0",
"path": "^0.11.14",
"reflect-metadata": "^0.1.3",

View File

@ -3,6 +3,7 @@ import {Post} from "./entity/Post";
import {PostDetails} from "./entity/PostDetails";
import {Image} from "./entity/Image";
import {ImageDetails} from "./entity/ImageDetails";
import {Cover} from "./entity/Cover";
// first create a connection
let options = {
@ -14,7 +15,7 @@ let options = {
autoSchemaCreate: true
};
TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails]).then(connection => {
TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails, Cover]).then(connection => {
const postJson = {
id: 1,
@ -26,11 +27,26 @@ TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails])
meta: "about-hello"
}
};
let postRepository = connection.getRepository<Post>(Post);
return postRepository.findById(1).then(post => {
console.log(post);
}, err => console.log(err));
let qb = postRepository
.createQueryBuilder("post")
.addSelect("image")
.addSelect("imageDetails")
.addSelect("secondaryImage")
.addSelect("cover")
.leftJoin("post.images", "image", "on", "image.post=post.id")
.leftJoin("post.secondaryImages", "secondaryImage", "on", "secondaryImage.secondaryPost=post.id")
.leftJoin("image.details", "imageDetails", "on", "imageDetails.id=image.details")
.innerJoin("post.cover", "cover", "on", "cover.id=post.cover")
//.leftJoin(Image, "image", "on", "image.post=post.id")
//.where("post.id=:id")
.setParameter("id", 1);
return postRepository
.queryMany(qb.getSql(), qb.generateAliasMap())
.then(result => console.log(JSON.stringify(result, null, 4)))
.catch(err => console.log(err));
return;
@ -41,11 +57,11 @@ TypeORM.createMysqlConnection(options, [Post, PostDetails, Image, ImageDetails])
const post = new Post();
post.text = "Hello how are you?";
post.title = "hello";
post.details = details;
//post.details = details;
postRepository
.persist(post)
.then(post => console.log("Post has been saved"))
.catch(error => console.log("Cannot save. Error: ", error));
}, error => console.log("Cannot connect: ", error));
}).catch(error => console.log("Cannot connect: ", error));

View File

@ -0,0 +1,18 @@
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {OneToMany} from "../../../src/decorator/Relations";
import {Post} from "./Post";
@Table("sample2_cover")
export class Cover {
@PrimaryColumn("int", { isAutoIncrement: true })
id: number;
@Column()
url: string;
@OneToMany<Post>(() => Post, post => post.cover)
posts: Post[];
}

View File

@ -2,6 +2,7 @@ import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {ManyToOne, OneToMany, OneToOne} from "../../../src/decorator/Relations";
import {Post} from "./Post";
import {ImageDetails} from "./ImageDetails";
@Table("sample2_image")
export class Image {
@ -12,21 +13,13 @@ export class Image {
@Column()
name: string;
@ManyToOne<Post>(() => Post, post => post.images, {
//isAlwaysLeftJoin: true
})
@ManyToOne<Post>(() => Post, post => post.images)
post: Post;
@ManyToOne<Post>(() => Post, post => post.secondaryImages, {
// isAlwaysLeftJoin: true
})
@ManyToOne<Post>(() => Post, post => post.secondaryImages)
secondaryPost: Post;
/*
@OneToOne<ImageDetails>(true, () => ImageDetails, details => details.image, {
isAlwaysInnerJoin: true
})
details: ImageDetails;*/
@OneToOne<ImageDetails>(true, () => ImageDetails, details => details.image)
details: ImageDetails;
}

View File

@ -1,8 +1,8 @@
import {PrimaryColumn, Column} from "../../../src/decorator/Columns";
import {Table} from "../../../src/decorator/Tables";
import {OneToOne, OneToMany} from "../../../src/decorator/Relations";
import {PostDetails} from "./PostDetails";
import {OneToMany, ManyToOne} from "../../../src/decorator/Relations";
import {Image} from "./Image";
import {Cover} from "./Cover";
@Table("sample2_post")
export class Post {
@ -20,19 +20,16 @@ export class Post {
})
text: string;
/* @OneToOne<PostDetails>(true, () => PostDetails, details => details.post, {
//isAlwaysInnerJoin: true
})
/* @OneToOne<PostDetails>(true, () => PostDetails, details => details.post)
details: PostDetails;*/
@OneToMany<Image>(() => Image, image => image.post, {
isAlwaysLeftJoin: true
})
@OneToMany<Image>(() => Image, image => image.post)
images: Image[];
@OneToMany<Image>(() => Image, image => image.secondaryPost, {
isAlwaysLeftJoin: true
})
@OneToMany<Image>(() => Image, image => image.secondaryPost)
secondaryImages: Image[];
@ManyToOne<Cover>(() => Cover, cover => cover.posts)
cover: Cover;
}

View File

@ -1,5 +1,52 @@
import {EntityMetadata} from "../../metadata-builder/metadata/EntityMetadata";
import {ColumnMetadata} from "../../metadata-builder/metadata/ColumnMetadata";
export class Alias {
isMain: boolean;
entityMetadata: EntityMetadata;
name: string;
parentPropertyName: string;
parentAliasName: string;
constructor(name: string, entityMetadata: EntityMetadata, parentAliasName?: string, parentPropertyName?: string) {
this.name = name;
this.entityMetadata = entityMetadata;
this.parentAliasName = parentAliasName;
this.parentPropertyName = parentPropertyName;
}
}
export class AliasMap {
constructor(public aliases: Alias[] = []) {
}
addMainAlias(alias: Alias) {
const mainAlias = this.getMainAlias();
if (mainAlias)
this.aliases.splice(this.aliases.indexOf(mainAlias), 1);
alias.isMain = true;
this.aliases.push(alias);
}
addAlias(alias: Alias) {
this.aliases.push(alias);
}
getMainAlias() {
return this.aliases.find(alias => alias.isMain);
}
findAliasByName(name: string) {
return this.aliases.find(alias => alias.name === name);
}
findAliasByParent(parentAliasName: string, parentPropertyName: string) {
return this.aliases.find(alias => {
return alias.parentAliasName === parentAliasName && alias.parentPropertyName === parentPropertyName;
});
}
}
/**
* @author Umed Khudoiberdiev <info@zar.tj>
*/
@ -18,9 +65,9 @@ export class QueryBuilder {
private type: "select"|"update"|"delete";
private selects: string[] = [];
private froms: { entity: Function, alias: string };
private leftJoins: { join: Function, alias: string, conditionType: string, condition: string }[] = [];
private innerJoins: { join: Function, alias: string, conditionType: string, condition: string }[] = [];
private froms: { alias: Alias };
private leftJoins: { alias: Alias, conditionType: string, condition: string }[] = [];
private innerJoins: { alias: Alias, conditionType: string, condition: string }[] = [];
private groupBys: string[] = [];
private wheres: { type: "simple"|"and"|"or", condition: string }[] = [];
private havings: { type: "simple"|"and"|"or", condition: string }[] = [];
@ -29,6 +76,8 @@ export class QueryBuilder {
private limit: number;
private offset: number;
private aliasMap = new AliasMap();
// -------------------------------------------------------------------------
// Public Methods
// -------------------------------------------------------------------------
@ -74,17 +123,49 @@ export class QueryBuilder {
//from(tableName: string, alias: string): this;
from(entity: Function, alias?: string): this {
//from(entityOrTableName: Function|string, alias: string): this {
this.froms = { entity: entity, alias: alias };
const aliasObj = new Alias(alias, this.findMetadata(entity));
this.aliasMap.addMainAlias(aliasObj);
this.froms = { alias: aliasObj };
return this;
}
innerJoin(target: Function, alias: string, conditionType: string, condition: string): this {
this.innerJoins.push({ join: target, alias: alias, conditionType: conditionType, condition: condition });
innerJoin(property: string, alias: string, conditionType: string, condition: string): this;
innerJoin(entity: Function, alias: string, conditionType: string, condition: string): this;
innerJoin(entityOrProperty: Function|string, alias: string, conditionType: string, condition: string): this {
let parentPropertyName = "", parentAliasName = "";
let entityMetadata: EntityMetadata;
if (entityOrProperty instanceof Function) {
entityMetadata = this.findMetadata(entityOrProperty);
} else {
parentAliasName = (<string> entityOrProperty).split(".")[0];
parentPropertyName = (<string> entityOrProperty).split(".")[1];
const parentAliasMetadata = this.aliasMap.findAliasByName(parentAliasName).entityMetadata;
entityMetadata = parentAliasMetadata.findRelationWithDbName(parentPropertyName).relatedEntityMetadata;
}
const aliasObj = new Alias(alias, entityMetadata, parentAliasName, parentPropertyName);
this.aliasMap.addAlias(aliasObj);
this.innerJoins.push({ alias: aliasObj, conditionType: conditionType, condition: condition });
return this;
}
leftJoin(target: Function, alias: string, conditionType: string, condition: string): this {
this.leftJoins.push({ join: target, alias: alias, conditionType: conditionType, condition: condition });
leftJoin(property: string, alias: string, conditionType: string, condition: string): this;
leftJoin(entity: Function, alias: string, conditionType: string, condition: string): this;
leftJoin(entityOrProperty: Function|string, alias: string, conditionType: string, condition: string): this {
let parentPropertyName = "", parentAliasName = "";
let entityMetadata: EntityMetadata;
if (entityOrProperty instanceof Function) {
entityMetadata = this.findMetadata(entityOrProperty);
} else {
parentAliasName = (<string> entityOrProperty).split(".")[0];
parentPropertyName = (<string> entityOrProperty).split(".")[1];
const parentAliasMetadata = this.aliasMap.findAliasByName(parentAliasName).entityMetadata;
entityMetadata = parentAliasMetadata.findRelationByPropertyName(parentPropertyName).relatedEntityMetadata;
}
const aliasObj = new Alias(alias, entityMetadata, parentAliasName, parentPropertyName);
this.aliasMap.addAlias(aliasObj);
this.leftJoins.push({ alias: aliasObj, conditionType: conditionType, condition: condition });
return this;
}
@ -148,7 +229,7 @@ export class QueryBuilder {
return this;
}
setParameter(key: string, value: string): this {
setParameter(key: string, value: any): this {
this.parameters[key] = value;
return this;
}
@ -171,6 +252,13 @@ export class QueryBuilder {
sql = this.replaceParameters(sql);
return sql;
}
generateAliasMap(): AliasMap {
return this.aliasMap;
/* const aliasesFromInnerJoins = this.innerJoins.map(join => join.alias);
const aliasesFromLeftJoins = this.leftJoins.map(join => join.alias);
return new AliasMap([this.froms.alias, ...aliasesFromLeftJoins, ...aliasesFromInnerJoins]);*/
}
// -------------------------------------------------------------------------
// Protected Methods
@ -196,7 +284,7 @@ export class QueryBuilder {
protected findMetadata(target: Function) {
const metadata = this.entityMetadatas.find(metadata => metadata.target === target);
if (!metadata)
throw new Error("Metadata for " + this.froms.entity + " was not found.");
throw new Error("Metadata for " + (<any>target).name + " was not found.");
return metadata;
}
@ -204,24 +292,24 @@ export class QueryBuilder {
protected createSelectExpression() {
// todo throw exception if selects or from is missing
const metadata = this.findMetadata(this.froms.entity);
const metadata = this.froms.alias.entityMetadata;
const tableName = metadata.table.name;
const alias = this.froms.alias ? this.froms.alias : metadata.table.name;
const alias = this.froms.alias.name;
const columns: string[] = [];
// add select from the main table
if (this.selects.indexOf(this.froms.alias) !== -1)
if (this.selects.indexOf(alias) !== -1)
metadata.columns.forEach(column => {
columns.push(this.froms.alias + "." + column.name + " AS " + this.froms.alias + "_" + column.name);
columns.push(alias + "." + column.name + " AS " + alias + "_" + column.name);
});
// add selects from left and inner joins
this.leftJoins.concat(this.innerJoins)
.filter(join => this.selects.indexOf(join.alias) !== -1)
.filter(join => this.selects.indexOf(join.alias.name) !== -1)
.forEach(join => {
const joinMetadata = this.findMetadata(join.join);
const joinMetadata = join.alias.entityMetadata;
joinMetadata.columns.forEach(column => {
columns.push(join.alias + "." + column.name + " AS " + join.alias + "_" + column.name);
columns.push(join.alias.name + "." + column.name + " AS " + join.alias.name + "_" + column.name);
});
});
@ -255,9 +343,9 @@ export class QueryBuilder {
if (!this.innerJoins || !this.innerJoins.length) return "";
return this.innerJoins.map(join => {
const joinMetadata = this.entityMetadatas.find(metadata => metadata.target === join.join); // todo: throw exception if not found
const joinMetadata = join.alias.entityMetadata; // todo: throw exception if not found
const relationTable = joinMetadata.table.name;
return " INNER JOIN " + relationTable + " " + join.alias + " " + join.conditionType + " " + join.condition;
return " INNER JOIN " + relationTable + " " + join.alias.name + " " + join.conditionType + " " + join.condition;
}).join(" ");
}
@ -265,9 +353,9 @@ export class QueryBuilder {
if (!this.leftJoins || !this.leftJoins.length) return "";
return this.leftJoins.map(join => {
const joinMetadata = this.findMetadata(join.join);
const joinMetadata = join.alias.entityMetadata;
const relationTable = joinMetadata.table.name;
return " LEFT JOIN " + relationTable + " " + join.alias + " " + join.conditionType + " " + join.condition;
return " LEFT JOIN " + relationTable + " " + join.alias.name + " " + join.conditionType + " " + join.condition;
}).join(" ");
}
@ -311,9 +399,5 @@ export class QueryBuilder {
});
return sql;
}
protected replaceTableNames(sql: string) {
return sql.replace("\$\$", "");
}
}

View File

@ -71,16 +71,6 @@ export class RelationMetadata extends PropertyMetadata {
*/
private _isCascadeRemove: boolean;
/**
* If set to true then it means that related object always will be left-joined when this object is being loaded.
*/
private _isAlwaysLeftJoin: boolean;
/**
* If set to true then it means that related object always will be inner-joined when this object is being loaded.
*/
private _isAlwaysInnerJoin: boolean;
/**
* Indicates if relation column value can be nullable or not.
*/
@ -115,10 +105,6 @@ export class RelationMetadata extends PropertyMetadata {
if (options.name)
this._name = options.name;
if (options.isAlwaysInnerJoin)
this._isAlwaysInnerJoin = options.isAlwaysInnerJoin;
if (options.isAlwaysLeftJoin)
this._isAlwaysLeftJoin = options.isAlwaysLeftJoin;
if (options.isCascadeInsert)
this._isCascadeInsert = options.isCascadeInsert;
if (options.isCascadeUpdate)
@ -178,14 +164,6 @@ export class RelationMetadata extends PropertyMetadata {
return this._isCascadeRemove;
}
get isAlwaysLeftJoin(): boolean {
return this._isAlwaysLeftJoin;
}
get isAlwaysInnerJoin(): boolean {
return this._isAlwaysInnerJoin;
}
get isOneToOne(): boolean {
return this.relationType === RelationTypes.ONE_TO_ONE;
}

View File

@ -20,16 +20,6 @@ export interface RelationOptions {
*/
isCascadeRemove?: boolean;
/**
* If set to true then it means that related object always will be left-joined when this object is being loaded.
*/
isAlwaysLeftJoin?: boolean;
/**
* If set to true then it means that related object always will be inner-joined when this object is being loaded.
*/
isAlwaysInnerJoin?: boolean;
/**
* Old column name. Used to make safe schema updates.
*/

View File

@ -1,7 +1,7 @@
import {Connection} from "../connection/Connection";
import {EntityMetadata} from "../metadata-builder/metadata/EntityMetadata";
import {OrmBroadcaster} from "../subscriber/OrmBroadcaster";
import {QueryBuilder} from "../driver/query-builder/QueryBuilder";
import {QueryBuilder, AliasMap} from "../driver/query-builder/QueryBuilder";
import {DynamicCascadeOptions} from "./cascade/CascadeOption";
import {EntityCreator} from "./creator/EntityCreator";
@ -87,34 +87,33 @@ export class Repository<Entity> {
/**
* Creates a new query builder that can be used to build an sql query.
*/
createQueryBuilder(alias?: string): QueryBuilder {
const queryBuilder = this.connection.driver.createQueryBuilder(this.connection.metadatas);
if (alias)
queryBuilder.select(alias).from(this.metadata.target, alias);
return queryBuilder;
createQueryBuilder(alias: string): QueryBuilder {
return this.connection.driver
.createQueryBuilder(this.connection.metadatas)
.select(alias)
.from(this.metadata.target, alias);
}
/**
* Executes query. Expects query will return object in Entity format and creates Entity object from that result.
*/
queryOne(query: string): Promise<Entity> {
queryOne(query: string, aliasMap: AliasMap): Promise<Entity> {
return this.connection.driver
.query<any[]>(query)
.then(results => this.createFromJson(results[0]))
.then(entity => {
this.broadcaster.broadcastAfterLoaded(entity);
return entity;
.then(results => this.objectToEntity(results, aliasMap))
.then(entities => {
this.broadcaster.broadcastAfterLoaded(entities[0]);
return entities[0];
});
}
/**
* Executes query. Expects query will return objects in Entity format and creates Entity objects from that result.
*/
queryMany(query: string): Promise<Entity[]> {
queryMany(query: string, aliasMap: AliasMap): Promise<Entity[]> {
return this.connection.driver
.query<any[]>(query)
.then(results => this.createManyFromJson(results))
.then(results => this.objectToEntity(results, aliasMap))
.then(entities => {
this.broadcaster.broadcastAfterLoadedAll(entities);
return entities;
@ -141,34 +140,37 @@ export class Repository<Entity> {
* Finds entities that match given conditions.
*/
find(conditions?: Object): Promise<Entity[]> {
const builder = this.createQueryBuilder("entity");
const alias = this.metadata.table.name;
const builder = this.createQueryBuilder(alias);
Object.keys(conditions).forEach(key => {
builder.where("entity." + key + "=:" + key).setParameter(key, (<any> conditions)[key]);
builder.where(alias + "." + key + "=:" + key).setParameter(key, (<any> conditions)[key]);
});
return this.queryMany(builder.getSql());
return this.queryMany(builder.getSql(), builder.generateAliasMap());
}
/**
* Finds one entity that matches given condition.
*/
findOne(conditions: Object): Promise<Entity> {
const builder = this.createQueryBuilder("entity");
const alias = this.metadata.table.name;
const builder = this.createQueryBuilder(alias);
Object.keys(conditions).forEach(key => {
builder.where("entity." + key + "=:" + key).setParameter(key, (<any> conditions)[key]);
builder.where(alias + "." + key + "=:" + key).setParameter(key, (<any> conditions)[key]);
});
return this.queryOne(builder.getSql());
return this.queryOne(builder.getSql(), builder.generateAliasMap());
}
/**
* Finds entity with given id.
*/
findById(id: any): Promise<Entity> {
const builder = this.createQueryBuilder("entity")
.where("entity." + this.metadata.primaryColumn.name + "=:id")
const alias = this.metadata.table.name;
const builder = this.createQueryBuilder(alias)
.where(alias + "." + this.metadata.primaryColumn.name + "=:id")
.setParameter("id", id);
return this.queryOne(builder.getSql());
return this.queryOne(builder.getSql(), builder.generateAliasMap());
}
// -------------------------------------------------------------------------
@ -268,6 +270,16 @@ export class Repository<Entity> {
// Private Methods
// -------------------------------------------------------------------------
/**
* Creates entity from the given json data. If fetchAllData param is specified then entity data will be
* loaded from the database first, then filled with given json data.
*/
private objectToEntity(objects: any, aliasMap: AliasMap) {
const creator = new EntityCreator(this.connection);
return creator.objectToEntity<Entity>(objects, this.metadata, aliasMap);
}
/*private dbObjectToEntity(dbObject: any): Promise<Entity> {
const hydrator = new EntityHydrator<Entity>(this.connection);
return hydrator.hydrate(this.metadata, dbObject, joinFields);

View File

@ -1,6 +1,8 @@
import {Connection} from "../../connection/Connection";
import {EntityMetadata} from "../../metadata-builder/metadata/EntityMetadata";
import {RelationMetadata} from "../../metadata-builder/metadata/RelationMetadata";
import {AliasMap, Alias} from "../../driver/query-builder/QueryBuilder";
import * as _ from "lodash";
export class EntityCreator {
@ -25,14 +27,24 @@ export class EntityCreator {
createFromJson<Entity>(object: any, metadata: EntityMetadata, fetchProperty?: boolean): Promise<Entity>;
createFromJson<Entity>(object: any, metadata: EntityMetadata, fetchProperty?: Object): Promise<Entity>;
createFromJson<Entity>(object: any, metadata: EntityMetadata, fetchOption?: boolean|Object): Promise<Entity> {
return this.objectToEntity(object, metadata, fetchOption);
return Promise.resolve(this.objectToEntity(object, metadata, fetchOption));
//return this.objectToEntity(object, metadata, fetchOption);
}
objectToEntity<Entity>(objects: any[], metadata: EntityMetadata, aliasMap: AliasMap, fetchProperty?: boolean): Entity;
objectToEntity<Entity>(objects: any[], metadata: EntityMetadata, aliasMap: AliasMap,fetchProperty?: Object): Entity;
objectToEntity<Entity>(objects: any[], metadata: EntityMetadata, aliasMap: AliasMap, fetchOption?: boolean|Object): Entity {
return this.toEntity(objects, metadata, aliasMap.getMainAlias(), aliasMap);
//return this.objectToEntity(object, metadata, fetchOption);
}
// -------------------------------------------------------------------------
// Private Methods
// -------------------------------------------------------------------------
getLoadMap(metadata: EntityMetadata) {
/*getLoadMap(metadata: EntityMetadata) {
const postId = 1;
const postJson = {
@ -59,7 +71,7 @@ export class EntityCreator {
const joinRelations = (parentTableAlias: string, entityMetadata: EntityMetadata) => {
if (visitedMetadatas.find(metadata => metadata === entityMetadata))
return;
visitedMetadatas.push(metadata);
entityMetadata.relations.filter(relation => relation.isAlwaysLeftJoin || relation.isAlwaysInnerJoin).forEach(relation => {
let relationAlias = relation.relatedEntityMetadata.table.name;
@ -81,7 +93,7 @@ export class EntityCreator {
} else { // else can be only always inner join
qb.addSelect(relationAlias).innerJoin(relation.type, relationAlias, "ON", condition);
}
// now recursively go throw its relations
joinRelations(relationAlias, relation.relatedEntityMetadata);
});
@ -101,15 +113,73 @@ export class EntityCreator {
private convertTableResultToJsonTree() {
}*/
private toEntity(sqlResult: any[], metadata: EntityMetadata, mainAlias: Alias, aliasMap: AliasMap): any[] {
const objects = _.groupBy(sqlResult, result => {
return result[mainAlias.name + "_" + metadata.primaryColumn.name];
});
return Object.keys(objects).map(key => {
//if (id && id != key) return null;
let isAnythingLoaded = false;
const object = objects[key][0];
//const entity = metadata.create();
const jsonObject: any = {};
metadata.columns.forEach(column => {
const valueInObject = object[mainAlias.name + "_" + column.name];
if (valueInObject && column.propertyName) { // todo: add check for property relation with id as a column
jsonObject[column.propertyName] = valueInObject;
isAnythingLoaded = true;
}
});
metadata.relations.forEach(relation => {
const alias = aliasMap.findAliasByParent(mainAlias.name, relation.propertyName);
if (alias) {
//const id = relation.isManyToOne || relation.isOneToOne ? object[mainAlias.name + "_" + relation.name] : null;
const relatedEntities = this.toEntity(sqlResult, relation.relatedEntityMetadata, alias, aliasMap);
if (relation.isManyToOne || relation.isOneToOne) {
const relatedObject = relatedEntities.find(obj => {
return obj[relation.relatedEntityMetadata.primaryColumn.name] === object[mainAlias.name + "_" + relation.name];
});
if (relatedObject) {
jsonObject[relation.propertyName] = relatedObject;
isAnythingLoaded = true;
}
} else if (relation.isOneToMany) {
const relatedObjects = relatedEntities.filter(obj => {
return obj[relation.inverseSideProperty] === object[mainAlias.name + "_" + metadata.primaryColumn.name];
});
//if (relatedObjects) {
jsonObject[relation.propertyName] = relatedObjects;
isAnythingLoaded = true;
//}
}
}
});
return isAnythingLoaded ? jsonObject : null;
}).filter(res => res !== null);
//return id ? final[0] : final;
}
private objectToEntity(object: any, metadata: EntityMetadata, doFetchProperties?: boolean): Promise<any>;
private objectToEntity(object: any, metadata: EntityMetadata, fetchConditions?: Object): Promise<any>;
private objectToEntity(object: any, metadata: EntityMetadata, fetchOption?: boolean|Object): Promise<any> {
private objectToEntity2(object: any, metadata: EntityMetadata, doFetchProperties?: boolean): Promise<any>;
private objectToEntity2(object: any, metadata: EntityMetadata, fetchConditions?: Object): Promise<any>;
private objectToEntity2(object: any, metadata: EntityMetadata, fetchOption?: boolean|Object): Promise<any> {
if (!object)
throw new Error("Given object is empty, cannot initialize empty object.");
this.getLoadMap(metadata);
//this.getLoadMap(metadata);
const doFetch = !!fetchOption;
const entityPromise = this.loadDependOnFetchOption(object, metadata, fetchOption);

View File

@ -62,7 +62,7 @@ export class DocumentHydrator<Document> {
let relationId = dbObject[relation.name];
let canLoadRelation = this.canLoadRelation(relation, joinFields);
let isLoadInnerTyped = this.isInnerJoin(joinFields, relation.name) || relation.isAlwaysInnerJoin;
let isLoadInnerTyped = this.isInnerJoin(joinFields, relation.name);
if (!canLoadRelation)
return;
@ -90,7 +90,7 @@ export class DocumentHydrator<Document> {
schema.relationWithManies.forEach(relation => {
let canLoadRelation = this.canLoadRelation(relation, joinFields);
let isLoadInnerTyped = this.isInnerJoin(joinFields, relation.name) || relation.isAlwaysInnerJoin;
let isLoadInnerTyped = this.isInnerJoin(joinFields, relation.name);
if (!canLoadRelation)
return;
@ -129,9 +129,7 @@ export class DocumentHydrator<Document> {
// -------------------------------------------------------------------------
private canLoadRelation(relation: RelationSchema, joinFields?: JoinFieldOption[]|any[]): boolean {
return this.hasKey(joinFields, relation.propertyName)
|| relation.isAlwaysLeftJoin
|| relation.isAlwaysInnerJoin;
return this.hasKey(joinFields, relation.propertyName);
}
private hasKey(joinFields: JoinFieldOption[]|any[], key: string) {

View File

@ -1,13 +1,14 @@
{
"ambientDevDependencies": {
"mocha": "github:DefinitelyTyped/DefinitelyTyped/mocha/mocha.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
"assertion-error": "github:DefinitelyTyped/DefinitelyTyped/assertion-error/assertion-error.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
"chai": "github:DefinitelyTyped/DefinitelyTyped/chai/chai.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
"sinon": "github:DefinitelyTyped/DefinitelyTyped/sinon/sinon.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
"mockery": "github:DefinitelyTyped/DefinitelyTyped/mockery/mockery.d.ts#6f6e5c7dd9effe21fee14eb65fe340ecbbc8580a"
"mocha": "github:DefinitelyTyped/DefinitelyTyped/mocha/mocha.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645",
"mockery": "github:DefinitelyTyped/DefinitelyTyped/mockery/mockery.d.ts#6f6e5c7dd9effe21fee14eb65fe340ecbbc8580a",
"sinon": "github:DefinitelyTyped/DefinitelyTyped/sinon/sinon.d.ts#7a3ca1f0b8a0960af9fc1838f3234cc9d6ce0645"
},
"ambientDependencies": {
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#cf7f980ba6cf09f75aaa9b5e53010db3c00b9aaf",
"es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#6697d6f7dadbf5773cb40ecda35a76027e0783b2"
"es6-shim": "github:DefinitelyTyped/DefinitelyTyped/es6-shim/es6-shim.d.ts#6697d6f7dadbf5773cb40ecda35a76027e0783b2",
"lodash": "github:DefinitelyTyped/DefinitelyTyped/lodash/lodash.d.ts#7b7aa2027a8fb6219a8bcf1b6bb12bcd0ff9539d",
"node": "github:DefinitelyTyped/DefinitelyTyped/node/node.d.ts#cf7f980ba6cf09f75aaa9b5e53010db3c00b9aaf"
}
}