mirror of
https://github.com/typeorm/typeorm.git
synced 2025-12-08 21:26:23 +00:00
metadata refactoring
This commit is contained in:
parent
3764579896
commit
eb78d759d7
@ -9,6 +9,11 @@ import {EntityMetadata} from "../metadata-builder/metadata/EntityMetadata";
|
||||
import {SchemaCreator} from "../schema-creator/SchemaCreator";
|
||||
import {MetadataNotFoundError} from "./error/MetadataNotFoundError";
|
||||
|
||||
interface RepositoryAndMetadata {
|
||||
repository: Repository<any>;
|
||||
metadata: EntityMetadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* A single connection instance to the database. Each connection has its own repositories, subscribers and metadatas.
|
||||
*/
|
||||
@ -23,7 +28,7 @@ export class Connection {
|
||||
private _metadatas: EntityMetadata[] = [];
|
||||
private _subscribers: OrmSubscriber<any>[] = [];
|
||||
private _broadcasters: OrmBroadcaster<any>[] = [];
|
||||
private _repositories: Repository<any>[] = [];
|
||||
private repositoryAndMetadatas: RepositoryAndMetadata[] = [];
|
||||
private _options: ConnectionOptions;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -79,7 +84,7 @@ export class Connection {
|
||||
* All repositories that are registered for this connection.
|
||||
*/
|
||||
get repositories(): Repository<any>[] {
|
||||
return this._repositories;
|
||||
return this.repositoryAndMetadatas.map(repoAndMeta => repoAndMeta.repository);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -120,7 +125,7 @@ export class Connection {
|
||||
addMetadatas(metadatas: EntityMetadata[]) {
|
||||
this._metadatas = this._metadatas.concat(metadatas);
|
||||
this._broadcasters = this._broadcasters.concat(metadatas.map(metadata => this.createBroadcasterForMetadata(metadata)));
|
||||
this._repositories = this._repositories.concat(metadatas.map(metadata => this.createRepositoryForMetadata(metadata)));
|
||||
this.repositoryAndMetadatas = this.repositoryAndMetadatas.concat(metadatas.map(metadata => this.createRepoMeta(metadata)));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -135,11 +140,11 @@ export class Connection {
|
||||
*/
|
||||
getRepository<Entity>(entityClass: Function): Repository<Entity> {
|
||||
const metadata = this.getMetadata(entityClass);
|
||||
const repository = this.repositories.find(repository => repository.metadata === metadata);
|
||||
if (!repository)
|
||||
const repoMeta = this.repositoryAndMetadatas.find(repoMeta => repoMeta.metadata === metadata);
|
||||
if (!repoMeta)
|
||||
throw new RepositoryNotFoundError(entityClass);
|
||||
|
||||
return repository;
|
||||
return repoMeta.repository;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -172,8 +177,11 @@ export class Connection {
|
||||
return new OrmBroadcaster<any>(this.subscribers, metadata.target);
|
||||
}
|
||||
|
||||
private createRepositoryForMetadata(metadata: EntityMetadata): Repository<any> {
|
||||
return new Repository<any>(this, metadata, this.getBroadcaster(metadata.target));
|
||||
private createRepoMeta(metadata: EntityMetadata): RepositoryAndMetadata {
|
||||
return {
|
||||
metadata: metadata,
|
||||
repository: new Repository<any>(this, metadata, this.getBroadcaster(metadata.target))
|
||||
};
|
||||
}
|
||||
|
||||
}
|
||||
@ -4,8 +4,8 @@ import {IndexMetadata} from "../../metadata-builder/metadata/IndexMetadata";
|
||||
/**
|
||||
* Fields that needs to be indexed must be marked with this decorator.
|
||||
*/
|
||||
export function Index() {
|
||||
export function Index(name?: string) {
|
||||
return function (object: Object, propertyName: string) {
|
||||
defaultMetadataStorage.addIndexMetadata(new IndexMetadata(object.constructor, propertyName));
|
||||
defaultMetadataStorage.addIndexMetadata(new IndexMetadata(object.constructor, propertyName, name));
|
||||
};
|
||||
}
|
||||
|
||||
@ -70,21 +70,6 @@ export class EntityMetadataBuilder {
|
||||
entityIndices = entityIndices.concat(inheritedIndices);
|
||||
});
|
||||
|
||||
// generate columns for relations
|
||||
/* const relationColumns = entityRelations
|
||||
.filter(relation => relation.isOwning && (relation.relationType === RelationTypes.ONE_TO_ONE || relation.relationType ===RelationTypes.MANY_TO_ONE))
|
||||
.filter(relation => !entityColumns.find(column => column.name === relation.name))
|
||||
.map(relation => {
|
||||
const options: ColumnOptions = {
|
||||
type: "int", // todo: setup proper inverse side type later
|
||||
oldColumnName: relation.oldColumnName,
|
||||
isNullable: relation.isNullable
|
||||
};
|
||||
return new ColumnMetadata(tableMetadata.target, relation.name, false, false, false, options);
|
||||
});
|
||||
|
||||
const allColumns = entityColumns.concat(relationColumns);*/
|
||||
|
||||
const entityMetadata = new EntityMetadata(tableMetadata, entityColumns, entityRelations, entityIndices, entityCompoundIndices, []);
|
||||
|
||||
// set naming strategies
|
||||
|
||||
@ -4,7 +4,7 @@ export class MetadataWithSuchNameAlreadyExistsError extends Error {
|
||||
constructor(metadataType: string, name: string) {
|
||||
super();
|
||||
this.message = metadataType + " metadata with such name " + name + " already exists. " +
|
||||
"Do you apply something twice? Or maybe try to change a name?";
|
||||
"Do you apply decorator twice? Or maybe try to change a name?";
|
||||
}
|
||||
|
||||
}
|
||||
@ -7,12 +7,40 @@ import {ColumnType} from "../types/ColumnTypes";
|
||||
* Constructor arguments for ColumnMetadata class.
|
||||
*/
|
||||
export interface ColumnMetadataArgs {
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
target: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this column is applied.
|
||||
*/
|
||||
propertyName: string;
|
||||
|
||||
/**
|
||||
* Indicates if this column is primary key or not.
|
||||
*/
|
||||
isPrimaryKey?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is create date column or not.
|
||||
*/
|
||||
isCreateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is update date column or not.
|
||||
*/
|
||||
isUpdateDate?: boolean;
|
||||
|
||||
/**
|
||||
* Indicates if this column is virtual or not.
|
||||
*/
|
||||
isVirtual?: boolean;
|
||||
|
||||
/**
|
||||
* Extra column options.
|
||||
*/
|
||||
options: ColumnOptions;
|
||||
}
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/**
|
||||
* This metadata interface contains all information about compound index on a document.
|
||||
* This metadata interface contains all information about table's compound index.
|
||||
*/
|
||||
export class CompoundIndexMetadata {
|
||||
|
||||
@ -7,6 +7,9 @@ export class CompoundIndexMetadata {
|
||||
// Private Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
private _target: Function;
|
||||
|
||||
/**
|
||||
@ -34,6 +37,9 @@ export class CompoundIndexMetadata {
|
||||
return this._target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fields combination to be used as index.
|
||||
*/
|
||||
get fields() {
|
||||
return this._fields;
|
||||
}
|
||||
|
||||
@ -10,9 +10,24 @@ export class ForeignKeyMetadata {
|
||||
// Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Table to which this foreign key is applied.
|
||||
*/
|
||||
private _table: TableMetadata;
|
||||
|
||||
/**
|
||||
* Array of columns.
|
||||
*/
|
||||
private _columns: ColumnMetadata[];
|
||||
|
||||
/**
|
||||
* Table to which this foreign key is references.
|
||||
*/
|
||||
private _referencedTable: TableMetadata;
|
||||
|
||||
/**
|
||||
* Array of referenced columns.
|
||||
*/
|
||||
private _referencedColumns: ColumnMetadata[];
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -30,34 +45,55 @@ export class ForeignKeyMetadata {
|
||||
// Accessors
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Table to which this foreign key is applied.
|
||||
*/
|
||||
get table(): TableMetadata {
|
||||
return this._table;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of columns.
|
||||
*/
|
||||
get columns(): ColumnMetadata[] {
|
||||
return this._columns;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table to which this foreign key is references.
|
||||
*/
|
||||
get referencedTable(): TableMetadata {
|
||||
return this._referencedTable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Array of referenced columns.
|
||||
*/
|
||||
get referencedColumns(): ColumnMetadata[] {
|
||||
return this._referencedColumns;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Array of column names.
|
||||
*/
|
||||
get columnNames(): string[] {
|
||||
return this.columns.map(column => column.name)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Array of referenced column names.
|
||||
*/
|
||||
get referencedColumnNames(): string[] {
|
||||
return this.referencedColumns.map(column => column.name)
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Foreign key name.
|
||||
*/
|
||||
get name() {
|
||||
const key = `${this.table.name}_${this.columnNames.join("_")}` +
|
||||
`_${this.referencedTable.name}_${this.referencedColumnNames.join("_")}`;
|
||||
return "fk_" + require('sha1')(key);
|
||||
return "fk_" + require('sha1')(key); // todo: use crypto instead?
|
||||
}
|
||||
|
||||
}
|
||||
@ -9,5 +9,15 @@ export class IndexMetadata extends PropertyMetadata {
|
||||
* The name of the index.
|
||||
*/
|
||||
name: string;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Constructor
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
constructor(target: Function, propertyName: string, name?: string) {
|
||||
super(target, propertyName);
|
||||
this.name = name; // todo: if there is no name, then generate it
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -1,4 +1,5 @@
|
||||
/**
|
||||
* Contains metadata information about ORM event subscribers.
|
||||
*/
|
||||
export class OrmEventSubscriberMetadata {
|
||||
|
||||
@ -6,6 +7,9 @@ export class OrmEventSubscriberMetadata {
|
||||
// Private Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
private _target: Function;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -7,7 +7,14 @@ export abstract class PropertyMetadata {
|
||||
// Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this decorator is applied.
|
||||
*/
|
||||
private _target: Function;
|
||||
|
||||
/**
|
||||
* Class's property name to which this decorator is applied.
|
||||
*/
|
||||
private _propertyName: string;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
@ -65,8 +65,10 @@ export class RelationMetadata extends PropertyMetadata {
|
||||
// Public Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Naming strategy used to generate and normalize column name.
|
||||
*/
|
||||
namingStrategy: NamingStrategy;
|
||||
// ownerEntityPropertiesMap: Object;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Private Properties
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
import {NamingStrategy} from "../../naming-strategy/NamingStrategy";
|
||||
|
||||
/**
|
||||
* This metadata interface contains all information about some table.
|
||||
* This metadata interface contains all information about specific table.
|
||||
*/
|
||||
export class TableMetadata {
|
||||
|
||||
@ -9,14 +9,28 @@ export class TableMetadata {
|
||||
// Public Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Naming strategy used to generate and normalize table name.
|
||||
*/
|
||||
namingStrategy: NamingStrategy;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Private Properties
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Class to which this column is applied.
|
||||
*/
|
||||
private _target: Function;
|
||||
|
||||
/**
|
||||
* Table name in the database.
|
||||
*/
|
||||
private _name: string;
|
||||
|
||||
/**
|
||||
* Indicates if this table is abstract or not. Regular tables can inherit columns from abstract tables.
|
||||
*/
|
||||
private _isAbstract: boolean;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
@ -41,10 +55,16 @@ export class TableMetadata {
|
||||
return this._target;
|
||||
}
|
||||
|
||||
/**
|
||||
* Table name in the database.
|
||||
*/
|
||||
get name() {
|
||||
return this.namingStrategy ? this.namingStrategy.tableName(this._name) : this._name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates if this table is abstract or not. Regular tables can inherit columns from abstract tables.
|
||||
*/
|
||||
get isAbstract() {
|
||||
return this._isAbstract;
|
||||
}
|
||||
|
||||
@ -1,4 +1,3 @@
|
||||
|
||||
/**
|
||||
* Describes all relation's options.
|
||||
*/
|
||||
|
||||
@ -20,8 +20,19 @@ export class Repository<Entity> {
|
||||
// Properties
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private _connection: Connection;
|
||||
private _metadata: EntityMetadata;
|
||||
/**
|
||||
* Connection used by this repository.
|
||||
*/
|
||||
private connection: Connection;
|
||||
|
||||
/**
|
||||
* Entity metadata of the table with which this repository is working.
|
||||
*/
|
||||
private metadata: EntityMetadata;
|
||||
|
||||
/**
|
||||
* Broadcaster used to broadcast this repository events.
|
||||
*/
|
||||
private broadcaster: OrmBroadcaster<Entity>;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
@ -31,23 +42,11 @@ export class Repository<Entity> {
|
||||
constructor(connection: Connection,
|
||||
metadata: EntityMetadata,
|
||||
broadcaster: OrmBroadcaster<Entity>) {
|
||||
this._connection = connection;
|
||||
this._metadata = metadata;
|
||||
this.connection = connection;
|
||||
this.metadata = metadata;
|
||||
this.broadcaster = broadcaster;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Getter Methods
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
get metadata(): EntityMetadata {
|
||||
return this._metadata;
|
||||
}
|
||||
|
||||
get connection(): Connection {
|
||||
return this._connection;
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Public Methods
|
||||
// -------------------------------------------------------------------------
|
||||
@ -129,7 +128,7 @@ export class Repository<Entity> {
|
||||
const persistOperation = this.difference(dbEntity, entity);
|
||||
return persister.executePersistOperation(persistOperation);
|
||||
}).then(() => entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds entities that match given conditions.
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user