mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
refactored connection class
This commit is contained in:
parent
8d68c8c40b
commit
81e15a0a3c
@ -4,7 +4,6 @@ import {Repository} from "../repository/Repository";
|
||||
import {EventSubscriberInterface} from "../subscriber/EventSubscriberInterface";
|
||||
import {RepositoryNotFoundError} from "./error/RepositoryNotFoundError";
|
||||
import {EntityMetadata} from "../metadata/EntityMetadata";
|
||||
import {SchemaCreator} from "../schema-creator/SchemaCreator";
|
||||
import {ConstructorFunction} from "../common/ConstructorFunction";
|
||||
import {EntityListenerMetadata} from "../metadata/EntityListenerMetadata";
|
||||
import {EntityManager} from "../entity-manager/EntityManager";
|
||||
@ -27,6 +26,8 @@ import {NamingStrategyNotFoundError} from "./error/NamingStrategyNotFoundError";
|
||||
import {EntityManagerFactory} from "../entity-manager/EntityManagerFactory";
|
||||
import {RepositoryFactory} from "../repository/RepositoryFactory";
|
||||
import {SchemaCreatorFactory} from "../schema-creator/SchemaCreatorFactory";
|
||||
import {ReactiveRepositoryNotFoundError} from "./error/ReactiveRepositoryNotFoundError";
|
||||
import {RepositoryNotTreeError} from "./error/RepositoryNotTreeError";
|
||||
|
||||
/**
|
||||
* A single connection instance to the database. Each connection has its own repositories, subscribers and metadatas.
|
||||
@ -47,10 +48,6 @@ export class Connection {
|
||||
*/
|
||||
private reactiveRepositories: ReactiveRepository<any>[] = [];
|
||||
|
||||
private repositoryFactory = getFromContainer(RepositoryFactory);
|
||||
|
||||
private schemaCreatorFactory = getFromContainer(SchemaCreatorFactory);
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Readonly properties
|
||||
// -------------------------------------------------------------------------
|
||||
@ -192,7 +189,8 @@ export class Connection {
|
||||
await this.driver.clearDatabase();
|
||||
|
||||
const schemaBuilder = this.driver.createSchemaBuilder();
|
||||
const schemaCreator = this.schemaCreatorFactory.create(schemaBuilder, this.entityMetadatas);
|
||||
const schemaCreatorFactory = getFromContainer(SchemaCreatorFactory);
|
||||
const schemaCreator = schemaCreatorFactory.create(schemaBuilder, this.entityMetadatas);
|
||||
return schemaCreator.create();
|
||||
}
|
||||
|
||||
@ -302,7 +300,7 @@ export class Connection {
|
||||
if (!repository)
|
||||
throw new RepositoryNotFoundError(this.name, entityClassOrName);
|
||||
if (!metadata.table.isClosure)
|
||||
throw new Error(`Cannot get a tree repository. ${metadata.name} is not a tree table. Try to use @ClosureTable decorator instead of @Table.`);
|
||||
throw new RepositoryNotTreeError(entityClassOrName);
|
||||
|
||||
return <TreeRepository<Entity>> repository;
|
||||
}
|
||||
@ -310,14 +308,14 @@ export class Connection {
|
||||
/**
|
||||
* Gets reactive repository for the given entity class.
|
||||
*/
|
||||
getReactiveRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): ReactiveRepository<Entity> {
|
||||
getReactiveRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function|string): ReactiveRepository<Entity> {
|
||||
if (!this.isConnected)
|
||||
throw new NoConnectionForRepositoryError(this.name);
|
||||
|
||||
const metadata = this.entityMetadatas.findByTarget(entityClass);
|
||||
const metadata = this.entityMetadatas.findByNameOrTarget(entityClass);
|
||||
const repository = this.reactiveRepositories.find(repository => ReactiveRepository.ownsMetadata(repository, metadata));
|
||||
if (!repository)
|
||||
throw new RepositoryNotFoundError(this.name, entityClass); // todo throw ReactiveRepositoryNotFoundError
|
||||
throw new ReactiveRepositoryNotFoundError(this.name, entityClass);
|
||||
|
||||
return repository;
|
||||
}
|
||||
@ -325,16 +323,16 @@ export class Connection {
|
||||
/**
|
||||
* Gets reactive tree repository for the given entity class.
|
||||
*/
|
||||
getReactiveTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function): ReactiveTreeRepository<Entity> {
|
||||
getReactiveTreeRepository<Entity>(entityClass: ConstructorFunction<Entity>|Function|string): ReactiveTreeRepository<Entity> {
|
||||
if (!this.isConnected)
|
||||
throw new NoConnectionForRepositoryError(this.name);
|
||||
|
||||
const metadata = this.entityMetadatas.findByTarget(entityClass);
|
||||
const metadata = this.entityMetadatas.findByNameOrTarget(entityClass);
|
||||
const repository = this.reactiveRepositories.find(repository => ReactiveRepository.ownsMetadata(repository, metadata));
|
||||
if (!repository)
|
||||
throw new RepositoryNotFoundError(this.name, entityClass);
|
||||
if (!metadata.table.isClosure)
|
||||
throw new Error(`Cannot get a tree repository. ${metadata.name} is not a tree table. Try to use @ClosureTable decorator instead of @Table.`);
|
||||
throw new RepositoryNotTreeError(entityClass);
|
||||
|
||||
return <ReactiveTreeRepository<Entity>> repository;
|
||||
}
|
||||
@ -348,25 +346,32 @@ export class Connection {
|
||||
*/
|
||||
private buildMetadatas() {
|
||||
|
||||
// first register naming strategies
|
||||
const metadatas = defaultMetadataStorage().namingStrategyMetadatas.filterByClasses(this.namingStrategyClasses);
|
||||
metadatas.forEach(cls => this.namingStrategyMetadatas.push(cls));
|
||||
// take imported naming strategy metadatas
|
||||
defaultMetadataStorage()
|
||||
.namingStrategyMetadatas
|
||||
.filterByClasses(this.namingStrategyClasses)
|
||||
.forEach(namingStrategy => this.namingStrategyMetadatas.push(namingStrategy));
|
||||
|
||||
// second register subscriber metadatas
|
||||
const subscribers = defaultMetadataStorage()
|
||||
// take imported event subscribers
|
||||
defaultMetadataStorage()
|
||||
.eventSubscriberMetadatas
|
||||
.filterByClasses(this.subscriberClasses)
|
||||
.map(metadata => getFromContainer(metadata.target));
|
||||
this.eventSubscribers.push(...subscribers);
|
||||
.map(metadata => getFromContainer(metadata.target))
|
||||
.forEach(subscriber => this.eventSubscribers.push(subscriber));
|
||||
|
||||
// third register entity and entity listener metadatas
|
||||
const entityMetadataBuilder = new EntityMetadataBuilder(this.createNamingStrategy());
|
||||
const entityMetadatas = entityMetadataBuilder.build(this.entityClasses);
|
||||
const entityListenerMetadatas = defaultMetadataStorage().entityListenerMetadatas.filterByClasses(this.entityClasses);
|
||||
// take imported entity listeners
|
||||
defaultMetadataStorage()
|
||||
.entityListenerMetadatas
|
||||
.filterByClasses(this.entityClasses)
|
||||
.forEach(entityListener => this.entityListeners.push(entityListener));
|
||||
|
||||
entityMetadatas.forEach(cls => this.entityMetadatas.push(cls));
|
||||
entityListenerMetadatas.forEach(cls => this.entityListeners.push(cls));
|
||||
entityMetadatas.forEach(metadata => this.createRepository(metadata));
|
||||
// build entity metadatas for the current connection
|
||||
getFromContainer(EntityMetadataBuilder)
|
||||
.build(this.createNamingStrategy(), this.entityClasses)
|
||||
.forEach(metadata => {
|
||||
this.entityMetadatas.push(metadata);
|
||||
this.createRepository(metadata);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@ -387,14 +392,15 @@ export class Connection {
|
||||
* Creates repository and reactive repository for the given entity metadata.
|
||||
*/
|
||||
private createRepository(metadata: EntityMetadata) {
|
||||
const repositoryFactory = getFromContainer(RepositoryFactory);
|
||||
if (metadata.table.isClosure) {
|
||||
const repository = this.repositoryFactory.createRepository(this, this.entityMetadatas, metadata);
|
||||
const reactiveRepository = this.repositoryFactory.createReactiveRepository(repository);
|
||||
const repository = repositoryFactory.createRepository(this, this.entityMetadatas, metadata);
|
||||
const reactiveRepository = repositoryFactory.createReactiveRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
} else {
|
||||
const repository = this.repositoryFactory.createTreeRepository(this, this.entityMetadatas, metadata);
|
||||
const reactiveRepository = this.repositoryFactory.createReactiveTreeRepository(repository);
|
||||
const repository = repositoryFactory.createTreeRepository(this, this.entityMetadatas, metadata);
|
||||
const reactiveRepository = repositoryFactory.createReactiveTreeRepository(repository);
|
||||
this.repositories.push(repository);
|
||||
this.reactiveRepositories.push(reactiveRepository);
|
||||
}
|
||||
|
||||
14
src/connection/error/ReactiveRepositoryNotFoundError.ts
Normal file
14
src/connection/error/ReactiveRepositoryNotFoundError.ts
Normal file
@ -0,0 +1,14 @@
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class ReactiveRepositoryNotFoundError extends Error {
|
||||
name = "ReactiveRepositoryNotFoundError";
|
||||
|
||||
constructor(connectionName: string, entityClass: Function|string) {
|
||||
super();
|
||||
const targetName = typeof entityClass === "function" && (<any> entityClass).name ? (<any> entityClass).name : entityClass;
|
||||
this.message = `No reactive repository for "${targetName}" was found. Looks like this entity is not registered in ` +
|
||||
`current "${connectionName}" connection?`;
|
||||
}
|
||||
|
||||
}
|
||||
13
src/connection/error/RepositoryNotTreeError.ts
Normal file
13
src/connection/error/RepositoryNotTreeError.ts
Normal file
@ -0,0 +1,13 @@
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
export class RepositoryNotTreeError extends Error {
|
||||
name = "RepositoryNotTreeError";
|
||||
|
||||
constructor(entityClass: Function|string) {
|
||||
super();
|
||||
const targetName = typeof entityClass === "function" && (<any> entityClass).name ? (<any> entityClass).name : entityClass;
|
||||
this.message = `Repository of the "${targetName}" class is not a TreeRepository. Try to use @ClosureTable decorator instead of @Table.`;
|
||||
}
|
||||
|
||||
}
|
||||
@ -28,13 +28,6 @@ export class EntityMetadataBuilder {
|
||||
|
||||
private entityValidator = new EntityMetadataValidator();
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
constructor(private namingStrategy: NamingStrategyInterface) {
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
@ -53,7 +46,8 @@ export class EntityMetadataBuilder {
|
||||
/**
|
||||
* Builds a complete metadata aggregations for the given entity classes.
|
||||
*/
|
||||
build(entityClasses: Function[]): EntityMetadata[] {
|
||||
build(namingStrategy: NamingStrategyInterface,
|
||||
entityClasses: Function[]): EntityMetadata[] {
|
||||
|
||||
const allMetadataStorage = defaultMetadataStorage();
|
||||
|
||||
@ -62,20 +56,20 @@ export class EntityMetadataBuilder {
|
||||
const tableMetadatas = allTableMetadatas.filterByClasses(entityClasses).filter(table => !table.isAbstract);
|
||||
|
||||
// set naming strategy
|
||||
// allMetadataStorage.tableMetadatas.forEach(tableMetadata => tableMetadata.namingStrategy = this.namingStrategy);
|
||||
// allTableMetadatas.forEach(column => column.namingStrategy = this.namingStrategy);
|
||||
// entityMetadata.relations.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
// allMetadataStorage.tableMetadatas.forEach(tableMetadata => tableMetadata.namingStrategy = namingStrategy);
|
||||
// allTableMetadatas.forEach(column => column.namingStrategy = namingStrategy);
|
||||
// entityMetadata.relations.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
|
||||
const entityMetadatas = tableMetadatas.map(tableMetadata => {
|
||||
|
||||
const mergedMetadata = allMetadataStorage.mergeWithAbstract(allTableMetadatas, tableMetadata);
|
||||
|
||||
// set naming strategy
|
||||
// tableMetadata.namingStrategy = this.namingStrategy;
|
||||
mergedMetadata.columnMetadatas.forEach(column => column.namingStrategy = this.namingStrategy);
|
||||
mergedMetadata.relationMetadatas.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
mergedMetadata.indexMetadatas.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
mergedMetadata.compositeIndexMetadatas.forEach(relation => relation.namingStrategy = this.namingStrategy);
|
||||
// tableMetadata.namingStrategy = namingStrategy;
|
||||
mergedMetadata.columnMetadatas.forEach(column => column.namingStrategy = namingStrategy);
|
||||
mergedMetadata.relationMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
mergedMetadata.indexMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
mergedMetadata.compositeIndexMetadatas.forEach(relation => relation.namingStrategy = namingStrategy);
|
||||
|
||||
// merge indices and composite indices because simple indices actually are compose indices with only one column
|
||||
this.mergeIndicesAndCompositeIndices(mergedMetadata.indexMetadatas, mergedMetadata.compositeIndexMetadatas);
|
||||
@ -86,7 +80,7 @@ export class EntityMetadataBuilder {
|
||||
|
||||
// create a new entity metadata
|
||||
const entityMetadata = new EntityMetadata(
|
||||
this.namingStrategy,
|
||||
namingStrategy,
|
||||
tableMetadata,
|
||||
mergedMetadata.columnMetadatas,
|
||||
mergedMetadata.relationMetadatas,
|
||||
@ -180,7 +174,7 @@ export class EntityMetadataBuilder {
|
||||
entityMetadatas
|
||||
.filter(metadata => metadata.table.isClosure)
|
||||
.forEach(metadata => {
|
||||
const closureTableName = this.namingStrategy.closureJunctionTableName(metadata.table.name);
|
||||
const closureTableName = namingStrategy.closureJunctionTableName(metadata.table.name);
|
||||
const closureJunctionTableMetadata = new TableMetadata(undefined, closureTableName, "closureJunction");
|
||||
|
||||
const columns = [
|
||||
@ -212,7 +206,7 @@ export class EntityMetadataBuilder {
|
||||
}));
|
||||
}
|
||||
|
||||
const closureJunctionEntityMetadata = new EntityMetadata(this.namingStrategy, closureJunctionTableMetadata, columns, [], []);
|
||||
const closureJunctionEntityMetadata = new EntityMetadata(namingStrategy, closureJunctionTableMetadata, columns, [], []);
|
||||
closureJunctionEntityMetadata.foreignKeys.push(
|
||||
new ForeignKeyMetadata(closureJunctionTableMetadata, [columns[0]], metadata.table, [metadata.primaryColumn]),
|
||||
new ForeignKeyMetadata(closureJunctionTableMetadata, [columns[1]], metadata.table, [metadata.primaryColumn])
|
||||
@ -250,7 +244,7 @@ export class EntityMetadataBuilder {
|
||||
options: column2options
|
||||
})
|
||||
];
|
||||
const junctionEntityMetadata = new EntityMetadata(this.namingStrategy, tableMetadata, columns, [], []);
|
||||
const junctionEntityMetadata = new EntityMetadata(namingStrategy, tableMetadata, columns, [], []);
|
||||
junctionEntityMetadata.foreignKeys.push(
|
||||
new ForeignKeyMetadata(tableMetadata, [columns[0]], metadata.table, [column1]),
|
||||
new ForeignKeyMetadata(tableMetadata, [columns[1]], relation.inverseEntityMetadata.table, [column2])
|
||||
|
||||
7
src/metadata-storage/EntityMetadataFactory.ts
Normal file
7
src/metadata-storage/EntityMetadataFactory.ts
Normal file
@ -0,0 +1,7 @@
|
||||
export class EntityMetadataFactory {
|
||||
|
||||
createEntityMetadataBuilder() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user