refactored connection usages part

This commit is contained in:
Umed Khudoiberdiev 2016-04-30 00:29:08 +05:00
parent 68a775c475
commit ae26df1d1e
7 changed files with 98 additions and 108 deletions

View File

@ -62,7 +62,7 @@ export class Connection {
/**
* All subscribers that are registered for this connection.
*/
readonly subscriberMetadatas: EventSubscriberInterface<any>[] = [];
readonly eventSubscribers: EventSubscriberInterface<any>[] = [];
// -------------------------------------------------------------------------
// Private Properties
@ -263,7 +263,7 @@ export class Connection {
.eventSubscriberMetadatas
.filterByClasses(this.subscriberClasses)
.map(metadata => this.createContainerInstance(metadata.target));
this.subscriberMetadatas.push(...subscribers);
this.eventSubscribers.push(...subscribers);
// third register entity and entity listener metadatas
const entityMetadataBuilder = new EntityMetadataBuilder(this.createNamingStrategy());

View File

@ -28,6 +28,8 @@ export interface Driver {
readonly db: string;
/**
* todo: driver should not define which query builder to create, it should create its own helper for query builder.
*
* Creates a query builder which can be used to build an sql queries.
*/
readonly queryBuilderClass: Function;

View File

@ -1,4 +1,3 @@
import {Connection} from "../connection/Connection";
import {PersistOperation} from "./operation/PersistOperation";
import {RemoveOperation} from "./operation/RemoveOperation";
import {UpdateOperation} from "./operation/UpdateOperation";
@ -7,7 +6,8 @@ import {InsertOperation} from "./operation/InsertOperation";
import {JunctionRemoveOperation} from "./operation/JunctionRemoveOperation";
import {UpdateByRelationOperation} from "./operation/UpdateByRelationOperation";
import {Broadcaster} from "../subscriber/Broadcaster";
import {EntityMetadata} from "../metadata/EntityMetadata";
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
import {Driver} from "../driver/Driver";
/**
* Executes PersistOperation in the given connection.
@ -19,8 +19,9 @@ export class PersistOperationExecutor {
// Constructor
// -------------------------------------------------------------------------
constructor(private connection: Connection,
private entityMetadatas: EntityMetadata[]) {
constructor(private driver: Driver,
private entityMetadatas: EntityMetadataCollection,
private broadcaster: Broadcaster) {
}
// -------------------------------------------------------------------------
@ -31,11 +32,10 @@ export class PersistOperationExecutor {
* Executes given persist operation.
*/
executePersistOperation(persistOperation: PersistOperation) {
const broadcaster = new Broadcaster(this.connection, this.entityMetadatas);
return Promise.resolve()
.then(() => this.broadcastBeforeEvents(broadcaster, persistOperation))
.then(() => this.connection.driver.beginTransaction())
.then(() => this.broadcastBeforeEvents(persistOperation))
.then(() => this.driver.beginTransaction())
.then(() => this.executeInsertOperations(persistOperation))
.then(() => this.executeInsertJunctionsOperations(persistOperation))
.then(() => this.executeRemoveJunctionsOperations(persistOperation))
@ -43,10 +43,10 @@ export class PersistOperationExecutor {
.then(() => this.executeUpdateOperations(persistOperation))
.then(() => this.executeRemoveRelationOperations(persistOperation))
.then(() => this.executeRemoveOperations(persistOperation))
.then(() => this.connection.driver.endTransaction())
.then(() => this.driver.endTransaction())
.then(() => this.updateIdsOfInsertedEntities(persistOperation))
.then(() => this.updateIdsOfRemovedEntities(persistOperation))
.then(() => this.broadcastAfterEvents(broadcaster, persistOperation));
.then(() => this.broadcastAfterEvents(persistOperation));
}
// -------------------------------------------------------------------------
@ -56,20 +56,20 @@ export class PersistOperationExecutor {
/**
* Broadcast all before persistment events - beforeInsert, beforeUpdate and beforeRemove events.
*/
private broadcastBeforeEvents(broadcaster: Broadcaster, persistOperation: PersistOperation) {
private broadcastBeforeEvents(persistOperation: PersistOperation) {
const insertEvents = persistOperation.inserts.map(insertOperation => {
const persistedEntityWithId = persistOperation.allPersistedEntities.find(e => e.entity === insertOperation.entity);
return broadcaster.broadcastBeforeInsertEvent(persistedEntityWithId.entity);
return this.broadcaster.broadcastBeforeInsertEvent(persistedEntityWithId.entity);
});
const updateEvents = persistOperation.updates.map(updateOperation => {
const persistedEntityWithId = persistOperation.allPersistedEntities.find(e => e.entity === updateOperation.entity);
return broadcaster.broadcastBeforeUpdateEvent(persistedEntityWithId.entity, updateOperation.columns);
return this.broadcaster.broadcastBeforeUpdateEvent(persistedEntityWithId.entity, updateOperation.columns);
});
const removeEvents = persistOperation.removes.map(removeOperation => {
// we can send here only dbEntity, not entity from the persisted object, since entity from the persisted
// object does not exist anymore - its removed, and there is no way to find this removed object
return broadcaster.broadcastBeforeRemoveEvent(removeOperation.entity, removeOperation.entityId);
return this.broadcaster.broadcastBeforeRemoveEvent(removeOperation.entity, removeOperation.entityId);
});
return Promise.all(insertEvents)
@ -80,20 +80,20 @@ export class PersistOperationExecutor {
/**
* Broadcast all after persistment events - afterInsert, afterUpdate and afterRemove events.
*/
private broadcastAfterEvents(broadcaster: Broadcaster, persistOperation: PersistOperation) {
private broadcastAfterEvents(persistOperation: PersistOperation) {
const insertEvents = persistOperation.inserts.map(insertOperation => {
const persistedEntity = persistOperation.allPersistedEntities.find(e => e.entity === insertOperation.entity);
return broadcaster.broadcastAfterInsertEvent(persistedEntity.entity);
return this.broadcaster.broadcastAfterInsertEvent(persistedEntity.entity);
});
const updateEvents = persistOperation.updates.map(updateOperation => {
const persistedEntityWithId = persistOperation.allPersistedEntities.find(e => e.entity === updateOperation.entity);
return broadcaster.broadcastAfterUpdateEvent(persistedEntityWithId.entity, updateOperation.columns);
return this.broadcaster.broadcastAfterUpdateEvent(persistedEntityWithId.entity, updateOperation.columns);
});
const removeEvents = persistOperation.removes.map(removeOperation => {
// we can send here only dbEntity, not entity from the persisted object, since entity from the persisted
// object does not exist anymore - its removed, and there is no way to find this removed object
return broadcaster.broadcastAfterRemoveEvent(removeOperation.entity, removeOperation.entityId);
return this.broadcaster.broadcastAfterRemoveEvent(removeOperation.entity, removeOperation.entityId);
});
return Promise.all(insertEvents)
@ -176,8 +176,7 @@ export class PersistOperationExecutor {
*/
private updateIdsOfInsertedEntities(persistOperation: PersistOperation) {
persistOperation.inserts.forEach(insertOperation => {
// const metadata = this.connection.getEntityMetadata(insertOperation.entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === insertOperation.entity.constructor);
const metadata = this.entityMetadatas.findByTarget(insertOperation.entity.constructor);
insertOperation.entity[metadata.primaryColumn.name] = insertOperation.entityId;
});
}
@ -187,8 +186,7 @@ export class PersistOperationExecutor {
*/
private updateIdsOfRemovedEntities(persistOperation: PersistOperation) {
persistOperation.removes.forEach(removeOperation => {
// const metadata = this.connection.getEntityMetadata(removeOperation.entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === removeOperation.entity.constructor);
const metadata = this.entityMetadatas.findByTarget(removeOperation.entity.constructor);
const removedEntity = persistOperation.allPersistedEntities.find(allNewEntity => {
return allNewEntity.entity.constructor === removeOperation.entity.constructor && allNewEntity.id === removeOperation.entity[metadata.primaryColumn.name];
});
@ -201,8 +199,7 @@ export class PersistOperationExecutor {
let tableName: string, relationName: string, relationId: any, idColumn: string, id: any;
const idInInserts = insertOperations.find(o => o.entity === operation.targetEntity).entityId;
if (operation.updatedRelation.isOneToMany) {
// const metadata = this.connection.getEntityMetadata(operation.insertOperation.entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === operation.insertOperation.entity.constructor);
const metadata = this.entityMetadatas.findByTarget(operation.insertOperation.entity.constructor);
tableName = metadata.table.name;
relationName = operation.updatedRelation.inverseRelation.name;
relationId = operation.targetEntity[metadata.primaryColumn.propertyName] || idInInserts;
@ -210,36 +207,34 @@ export class PersistOperationExecutor {
id = operation.insertOperation.entityId;
} else {
// const metadata = this.connection.getEntityMetadata(operation.targetEntity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === operation.targetEntity.constructor);
const metadata = this.entityMetadatas.findByTarget(operation.targetEntity.constructor);
tableName = metadata.table.name;
relationName = operation.updatedRelation.name;
relationId = operation.insertOperation.entityId;
idColumn = metadata.primaryColumn.name;
id = operation.targetEntity[metadata.primaryColumn.propertyName] || idInInserts;
}
return this.connection.driver.update(tableName, { [relationName]: relationId }, { [idColumn]: id });
return this.driver.update(tableName, { [relationName]: relationId }, { [idColumn]: id });
}
private update(updateOperation: UpdateOperation) {
const entity = updateOperation.entity;
// const metadata = this.connection.getEntityMetadata(entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === entity.constructor);
const metadata = this.entityMetadatas.findByTarget(entity.constructor);
const values: any = updateOperation.columns.reduce((object, column) => {
const value = this.connection.driver.preparePersistentValue(entity[column.propertyName], column);
const value = this.driver.preparePersistentValue(entity[column.propertyName], column);
(<any> object)[column.name] = value;
return object;
}, {});
if (metadata.updateDateColumn)
values[metadata.updateDateColumn.name] = this.connection.driver.preparePersistentValue(new Date(), metadata.updateDateColumn);
values[metadata.updateDateColumn.name] = this.driver.preparePersistentValue(new Date(), metadata.updateDateColumn);
return this.connection.driver.update(metadata.table.name, values, { [metadata.primaryColumn.name]: metadata.getEntityId(entity) });
return this.driver.update(metadata.table.name, values, { [metadata.primaryColumn.name]: metadata.getEntityId(entity) });
}
private updateDeletedRelations(removeOperation: RemoveOperation) { // todo: check if both many-to-one deletions work too
if (removeOperation.relation) {
return this.connection.driver.update(
return this.driver.update(
removeOperation.fromMetadata.table.name,
{ [removeOperation.relation.name]: null },
{ [removeOperation.fromMetadata.primaryColumn.name]: removeOperation.fromEntityId }
@ -250,14 +245,12 @@ export class PersistOperationExecutor {
}
private delete(entity: any) {
// const metadata = this.connection.getEntityMetadata(entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === entity.constructor);
return this.connection.driver.delete(metadata.table.name, { [metadata.primaryColumn.name]: entity[metadata.primaryColumn.propertyName] });
const metadata = this.entityMetadatas.findByTarget(entity.constructor);
return this.driver.delete(metadata.table.name, { [metadata.primaryColumn.name]: entity[metadata.primaryColumn.propertyName] });
}
private insert(entity: any) {
// const metadata = this.connection.getEntityMetadata(entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === entity.constructor);
const metadata = this.entityMetadatas.findByTarget(entity.constructor);
const columns = metadata.columns
.filter(column => !column.isVirtual)
.filter(column => entity.hasOwnProperty(column.propertyName))
@ -265,7 +258,7 @@ export class PersistOperationExecutor {
const values = metadata.columns
.filter(column => !column.isVirtual)
.filter(column => entity.hasOwnProperty(column.propertyName))
.map(column => this.connection.driver.preparePersistentValue(entity[column.propertyName], column));
.map(column => this.driver.preparePersistentValue(entity[column.propertyName], column));
const relationColumns = metadata.relations
.filter(relation => relation.isOwning && !!relation.relatedEntityMetadata)
.filter(relation => entity.hasOwnProperty(relation.propertyName))
@ -283,40 +276,36 @@ export class PersistOperationExecutor {
if (metadata.createDateColumn) {
allColumns.push(metadata.createDateColumn.name);
allValues.push(this.connection.driver.preparePersistentValue(new Date(), metadata.createDateColumn));
allValues.push(this.driver.preparePersistentValue(new Date(), metadata.createDateColumn));
}
if (metadata.updateDateColumn) {
allColumns.push(metadata.updateDateColumn.name);
allValues.push(this.connection.driver.preparePersistentValue(new Date(), metadata.updateDateColumn));
allValues.push(this.driver.preparePersistentValue(new Date(), metadata.updateDateColumn));
}
return this.connection.driver.insert(metadata.table.name, this.zipObject(allColumns, allValues));
return this.driver.insert(metadata.table.name, this.zipObject(allColumns, allValues));
}
private insertJunctions(junctionOperation: JunctionInsertOperation, insertOperations: InsertOperation[]) {
const junctionMetadata = junctionOperation.metadata;
// const metadata1 = this.connection.getEntityMetadata(junctionOperation.entity1.constructor);
// const metadata2 = this.connection.getEntityMetadata(junctionOperation.entity2.constructor);
const metadata1 = this.entityMetadatas.find(metadata => metadata.target === junctionOperation.entity1.constructor);
const metadata2 = this.entityMetadatas.find(metadata => metadata.target === junctionOperation.entity2.constructor);
const metadata1 = this.entityMetadatas.findByTarget(junctionOperation.entity1.constructor);
const metadata2 = this.entityMetadatas.findByTarget(junctionOperation.entity2.constructor);
const columns = junctionMetadata.columns.map(column => column.name);
const id1 = junctionOperation.entity1[metadata1.primaryColumn.name] || insertOperations.find(o => o.entity === junctionOperation.entity1).entityId;
const id2 = junctionOperation.entity2[metadata2.primaryColumn.name] || insertOperations.find(o => o.entity === junctionOperation.entity2).entityId;
const values = [id1, id2]; // todo: order may differ, find solution (column.table to compare with entity metadata table?)
return this.connection.driver.insert(junctionMetadata.table.name, this.zipObject(columns, values));
return this.driver.insert(junctionMetadata.table.name, this.zipObject(columns, values));
}
private removeJunctions(junctionOperation: JunctionRemoveOperation) {
const junctionMetadata = junctionOperation.metadata;
// const metadata1 = this.connection.getEntityMetadata(junctionOperation.entity1.constructor);
// const metadata2 = this.connection.getEntityMetadata(junctionOperation.entity2.constructor);
const metadata1 = this.entityMetadatas.find(metadata => metadata.target === junctionOperation.entity1.constructor);
const metadata2 = this.entityMetadatas.find(metadata => metadata.target === junctionOperation.entity2.constructor);
const metadata1 = this.entityMetadatas.findByTarget(junctionOperation.entity1.constructor);
const metadata2 = this.entityMetadatas.findByTarget(junctionOperation.entity2.constructor);
const columns = junctionMetadata.columns.map(column => column.name);
const id1 = junctionOperation.entity1[metadata1.primaryColumn.name];
const id2 = junctionOperation.entity2[metadata2.primaryColumn.name];
return this.connection.driver.delete(junctionMetadata.table.name, { [columns[0]]: id1, [columns[1]]: id2 });
return this.driver.delete(junctionMetadata.table.name, { [columns[0]]: id1, [columns[1]]: id2 });
}
private zipObject(keys: any[], values: any[]): Object {

View File

@ -4,6 +4,8 @@ import {Connection} from "../connection/Connection";
import {RawSqlResultsToEntityTransformer} from "./transformer/RawSqlResultsToEntityTransformer";
import {Broadcaster} from "../subscriber/Broadcaster";
import {EntityMetadata} from "../metadata/EntityMetadata";
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
import {Driver} from "../driver/Driver";
/**
* @internal
@ -21,7 +23,6 @@ export class QueryBuilder<Entity> {
// Private properties
// -------------------------------------------------------------------------
private broadcaster: Broadcaster;
private aliasMap: AliasMap;
private type: "select"|"update"|"delete";
private selects: string[] = [];
@ -44,10 +45,10 @@ export class QueryBuilder<Entity> {
// Constructor
// -------------------------------------------------------------------------
constructor(private connection: Connection,
private entityMetadatas: EntityMetadata[]) {
constructor(private driver: Driver,
private entityMetadatas: EntityMetadataCollection,
private broadcaster: Broadcaster) {
this.aliasMap = new AliasMap(entityMetadatas);
this.broadcaster = new Broadcaster(connection, this.entityMetadatas);
}
// -------------------------------------------------------------------------
@ -295,11 +296,11 @@ export class QueryBuilder<Entity> {
}
execute(): Promise<any> {
return this.connection.driver.query(this.getSql());
return this.driver.query(this.getSql());
}
getScalarResults<T>(): Promise<T[]> {
return this.connection.driver.query<T[]>(this.getSql());
return this.driver.query<T[]>(this.getSql());
}
getSingleScalarResult<T>(): Promise<T> {
@ -309,8 +310,7 @@ export class QueryBuilder<Entity> {
getResults(): Promise<Entity[]> {
const mainAlias = this.aliasMap.mainAlias.name;
if (this.firstResult || this.maxResults) {
// const metadata = this.connection.getEntityMetadata(this.fromEntity.alias.target);
const metadata = this.entityMetadatas.find(metadata => metadata.target === this.fromEntity.alias.target);
const metadata = this.entityMetadatas.findByTarget(this.fromEntity.alias.target);
let idsQuery = `SELECT DISTINCT(distinctAlias.${mainAlias}_${metadata.primaryColumn.name}) as ids`;
if (this.orderBys && this.orderBys.length > 0)
idsQuery += ", " + this.orderBys.map(orderBy => orderBy.sort.replace(".", "_")).join(", ");
@ -321,7 +321,7 @@ export class QueryBuilder<Entity> {
idsQuery += " LIMIT " + this.maxResults;
if (this.firstResult)
idsQuery += " OFFSET " + this.firstResult;
return this.connection.driver
return this.driver
.query<any[]>(idsQuery)
.then((results: any[]) => {
const ids = results.map(result => result["ids"]).join(", ");
@ -330,13 +330,13 @@ export class QueryBuilder<Entity> {
const queryWithIds = this.clone()
.andWhere(mainAlias + "." + metadata.primaryColumn.name + " IN (" + ids + ")")
.getSql();
return this.connection.driver.query<any[]>(queryWithIds);
return this.driver.query<any[]>(queryWithIds);
})
.then(results => this.rawResultsToEntities(results))
.then(results => this.broadcaster.broadcastLoadEventsForAll(results).then(() => results));
} else {
return this.connection.driver
return this.driver
.query<any[]>(this.getSql())
.then(results => this.rawResultsToEntities(results))
.then(results => this.broadcaster.broadcastLoadEventsForAll(results).then(() => results));
@ -349,12 +349,11 @@ export class QueryBuilder<Entity> {
getCount(): Promise<number> {
const mainAlias = this.aliasMap.mainAlias.name;
const metadata = this.entityMetadatas.find(metadata => metadata.target === this.fromEntity.alias.target);
// const metadata = this.connection.getEntityMetadata(this.fromEntity.alias.target);
const metadata = this.entityMetadatas.findByTarget(this.fromEntity.alias.target);
const countQuery = this.clone({ skipOrderBys: true })
.select(`COUNT(DISTINCT(${mainAlias}.${metadata.primaryColumn.name})) as cnt`)
.getSql();
return this.connection.driver
return this.driver
.query<any[]>(countQuery)
.then(results => parseInt(results[0]["cnt"]));
}
@ -367,7 +366,7 @@ export class QueryBuilder<Entity> {
}
clone(options?: { skipOrderBys?: boolean }) {
const qb = new QueryBuilder(this.connection, this.entityMetadatas);
const qb = new QueryBuilder(this.driver, this.entityMetadatas, this.broadcaster);
switch (this.type) {
case "select":
@ -441,7 +440,7 @@ export class QueryBuilder<Entity> {
// -------------------------------------------------------------------------
protected rawResultsToEntities(results: any[]) {
const transformer = new RawSqlResultsToEntityTransformer(this.connection, this.aliasMap);
const transformer = new RawSqlResultsToEntityTransformer(this.driver, this.aliasMap);
return transformer.transform(results);
}
@ -597,7 +596,7 @@ export class QueryBuilder<Entity> {
protected replaceParameters(sql: string) {
Object.keys(this.parameters).forEach(key => {
const value = this.parameters[key] !== null && this.parameters[key] !== undefined ? this.connection.driver.escape(this.parameters[key]) : "NULL";
const value = this.parameters[key] !== null && this.parameters[key] !== undefined ? this.driver.escape(this.parameters[key]) : "NULL";
sql = sql.replace(":" + key, value); // todo: make replace only in value statements, otherwise problems
});
return sql;

View File

@ -1,9 +1,8 @@
import {AliasMap} from "../alias/AliasMap";
import {Alias} from "../alias/Alias";
import * as _ from "lodash";
import {EntityMetadata} from "../../metadata/EntityMetadata";
import {Connection} from "../../connection/Connection";
import {OrmUtils} from "../../util/OrmUtils";
import {Driver} from "../../driver/Driver";
/**
* Transforms raw sql results returned from the database into entity object.
@ -17,7 +16,7 @@ export class RawSqlResultsToEntityTransformer {
// Constructor
// -------------------------------------------------------------------------
constructor(private connection: Connection,
constructor(private driver: Driver,
private aliasMap: AliasMap) {
}
@ -61,7 +60,7 @@ export class RawSqlResultsToEntityTransformer {
metadata.columns.forEach(column => {
const valueInObject = alias.getColumnValue(rawSqlResults[0], column); // we use zero index since its grouped data
if (valueInObject && column.propertyName && !column.isVirtual) {
entity[column.propertyName] = this.connection.driver.prepareHydratedValue(valueInObject, column);
entity[column.propertyName] = this.driver.prepareHydratedValue(valueInObject, column);
hasData = true;
}
});

View File

@ -7,19 +7,30 @@ import {EntityPersistOperationBuilder} from "../persistment/EntityPersistOperati
import {PersistOperationExecutor} from "../persistment/PersistOperationExecutor";
import {EntityWithId} from "../persistment/operation/PersistOperation";
import {FindOptions, FindOptionsUtils} from "./FindOptions";
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
import {Broadcaster} from "../subscriber/Broadcaster";
/**
* Repository is supposed to work with your entity objects. Find entities, insert, update, delete, etc.
*/
export class Repository<Entity> {
// -------------------------------------------------------------------------
// Private Properties
// -------------------------------------------------------------------------
private broadcaster: Broadcaster;
private persister: PersistOperationExecutor;
// -------------------------------------------------------------------------
// Constructor
// -------------------------------------------------------------------------
constructor(private connection: Connection,
private entityMetadatas: EntityMetadata[],
private entityMetadatas: EntityMetadataCollection,
private metadata: EntityMetadata) {
this.broadcaster = new Broadcaster(entityMetadatas, connection.eventSubscribers, connection.entityListeners);
this.persister = new PersistOperationExecutor(connection.driver, entityMetadatas, this.broadcaster);
}
// -------------------------------------------------------------------------
@ -42,8 +53,7 @@ export class Repository<Entity> {
*/
createQueryBuilder(alias: string): QueryBuilder<Entity> {
// const qb = this.connection.driver.createQueryBuilder<Entity>();
const cls: any = this.connection.driver.queryBuilderClass;
const qb = new cls(this.connection, this.entityMetadatas);
const qb = new QueryBuilder(this.connection.driver, this.entityMetadatas, this.broadcaster);
return qb
.select(alias)
.from(this.metadata.target, alias);
@ -93,7 +103,6 @@ export class Repository<Entity> {
*/
persist(entity: Entity): Promise<Entity> {
let loadedDbEntity: any;
const persister = new PersistOperationExecutor(this.connection, this.entityMetadatas);
const builder = new EntityPersistOperationBuilder(this.connection, this.entityMetadatas);
const allPersistedEntities = this.extractObjectsById(entity, this.metadata);
const promise: Promise<Entity> = !this.hasId(entity) ? Promise.resolve<Entity|null>(null) : this.initialize(entity);
@ -105,7 +114,7 @@ export class Repository<Entity> {
}) // need to find db entities that were not loaded by initialize method
.then(allDbEntities => {
const persistOperation = builder.buildFullPersistment(this.metadata, loadedDbEntity, entity, allDbEntities, allPersistedEntities);
return persister.executePersistOperation(persistOperation);
return this.persister.executePersistOperation(persistOperation);
}).then(() => entity);
}
@ -113,14 +122,13 @@ export class Repository<Entity> {
* Removes a given entity from the database.
*/
remove(entity: Entity): Promise<Entity> {
const persister = new PersistOperationExecutor(this.connection, this.entityMetadatas);
return this.initialize(entity).then(dbEntity => {
(<any> entity)[this.metadata.primaryColumn.name] = undefined;
const builder = new EntityPersistOperationBuilder(this.connection, this.entityMetadatas);
const dbEntities = this.extractObjectsById(dbEntity, this.metadata);
const allPersistedEntities = this.extractObjectsById(entity, this.metadata);
const persistOperation = builder.buildOnlyRemovement(this.metadata, dbEntity, entity, dbEntities, allPersistedEntities);
return persister.executePersistOperation(persistOperation);
return this.persister.executePersistOperation(persistOperation);
}).then(() => entity);
}

View File

@ -1,8 +1,8 @@
import {EventSubscriberInterface} from "./EventSubscriberInterface";
import {Connection} from "../connection/Connection";
import {ColumnMetadata} from "../metadata/ColumnMetadata";
import {EventListenerTypes} from "../metadata/types/EventListenerTypes";
import {EntityMetadata} from "../metadata/EntityMetadata";
import {EntityListenerMetadata} from "../metadata/EntityListenerMetadata";
import {EntityMetadataCollection} from "../metadata/collection/EntityMetadataCollection";
/**
* Broadcaster provides a helper methods to broadcast events to the subscribers.
@ -15,8 +15,9 @@ export class Broadcaster {
// Constructor
// -------------------------------------------------------------------------
constructor(private connection: Connection,
private entityMetadatas: EntityMetadata[]) {
constructor(private entityMetadatas: EntityMetadataCollection,
private subscriberMetadatas: EventSubscriberInterface<any>[],
private entityListeners: EntityListenerMetadata[]) {
}
// -------------------------------------------------------------------------
@ -25,13 +26,12 @@ export class Broadcaster {
broadcastBeforeInsertEvent(entity: any): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.beforeInsert)
.map(subscriber => subscriber.beforeInsert({ entity: entity }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.BEFORE_INSERT)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -41,13 +41,12 @@ export class Broadcaster {
broadcastBeforeUpdateEvent(entity: any, updatedColumns: ColumnMetadata[]): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.beforeUpdate)
.map(subscriber => subscriber.beforeUpdate({ entity: entity, updatedColumns: updatedColumns }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.BEFORE_UPDATE)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -57,13 +56,12 @@ export class Broadcaster {
broadcastBeforeRemoveEvent(entity: any, entityId: any): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.beforeRemove)
.map(subscriber => subscriber.beforeRemove({ entity: entity, entityId: entityId }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.BEFORE_REMOVE)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -73,13 +71,12 @@ export class Broadcaster {
broadcastAfterInsertEvent(entity: any): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.afterInsert)
.map(subscriber => subscriber.afterInsert({ entity: entity }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.AFTER_INSERT)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -89,13 +86,12 @@ export class Broadcaster {
broadcastAfterUpdateEvent(entity: any, updatedColumns: ColumnMetadata[]): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.afterUpdate)
.map(subscriber => subscriber.afterUpdate({ entity: entity, updatedColumns: updatedColumns }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.AFTER_UPDATE)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -105,13 +101,12 @@ export class Broadcaster {
broadcastAfterRemoveEvent(entity: any, entityId: any): Promise<void> {
const subscribers = this.connection
.subscriberMetadatas
const subscribers = this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.afterRemove)
.map(subscriber => subscriber.afterRemove({ entity: entity, entityId: entityId }));
const listeners = this.connection.entityListeners
const listeners = this.entityListeners
.filter(listener => listener.type === EventListenerTypes.AFTER_REMOVE)
.filter(listener => listener.target === entity.constructor)
.map(entityListener => entity[entityListener.propertyName]());
@ -120,7 +115,7 @@ export class Broadcaster {
}
broadcastLoadEvents(entity: any): Promise<void> {
// const metadata = this.connection.getEntityMetadata(entity.constructor);
// const metadata = this.getEntityMetadata(entity.constructor);
const metadata = this.entityMetadatas.find(metadata => metadata.target === entity.constructor);
let promises: Promise<any>[] = [];
@ -136,14 +131,12 @@ export class Broadcaster {
}
});
this.connection
.subscriberMetadatas
this.subscriberMetadatas
.filter(subscriber => this.isAllowedSubscribers(subscriber, entity))
.filter(subscriber => !!subscriber.afterLoad)
.forEach(subscriber => promises.push(<any> subscriber.afterLoad(entity)));
this.connection
.entityListeners
this.entityListeners
.filter(listener => listener.type === EventListenerTypes.AFTER_LOAD)
.filter(listener => listener.target === entity.constructor)
.forEach(listener => promises.push(<any> entity[listener.propertyName]()));