mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
refactored connection usages part
This commit is contained in:
parent
68a775c475
commit
ae26df1d1e
@ -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());
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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]()));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user