分离实体定义

定义架构

你可以使用装饰器在模型中定义实体及其列。 但有些人更喜欢在单独的文件中定义一个实体及其列,这些文件在TypeORM中称为”entity schemas”。

简单定义示例:

  1. import {EntitySchema} from "typeorm";
  2. export const CategoryEntity = new EntitySchema({
  3. name: "category",
  4. columns: {
  5. id: {
  6. type: Number,
  7. primary: true,
  8. generated: true
  9. },
  10. name: {
  11. type: String
  12. }
  13. }
  14. });

关系示例:

  1. import {EntitySchema} from "typeorm";
  2. export const PostEntity = new EntitySchema({
  3. name: "post",
  4. columns: {
  5. id: {
  6. type: Number,
  7. primary: true,
  8. generated: true
  9. },
  10. title: {
  11. type: String
  12. },
  13. text: {
  14. type: String
  15. }
  16. },
  17. relations: {
  18. categories: {
  19. type: "many-to-many",
  20. target: "category" // CategoryEntity
  21. }
  22. }
  23. });

复杂示例:

  1. import {EntitySchema} from "typeorm";
  2. export const PersonSchema = new EntitySchema({
  3. name: "person",
  4. columns: {
  5. id: {
  6. primary: true,
  7. type: "int",
  8. generated: "increment"
  9. },
  10. firstName: {
  11. type: String,
  12. length: 30
  13. },
  14. lastName: {
  15. type: String,
  16. length: 50,
  17. nullable: false
  18. },
  19. age: {
  20. type: Number,
  21. nullable: false
  22. }
  23. },
  24. checks: [
  25. { expression: `"firstName" <> 'John' AND "lastName" <> 'Doe'` },
  26. { expression: `"age" > 18` }
  27. ],
  28. indices: [
  29. {
  30. name: "IDX_TEST",
  31. unique: true,
  32. columns: [
  33. "firstName",
  34. "lastName"
  35. ]
  36. }
  37. ],
  38. uniques: [
  39. {
  40. name: "UNIQUE_TEST",
  41. columns: [
  42. "firstName",
  43. "lastName"
  44. ]
  45. }
  46. ]
  47. });

如果要使实体类型安全,可以定义模型并在模式定义中指定它:

  1. import {EntitySchema} from "typeorm";
  2. export interface Category {
  3. id: number;
  4. name: string;
  5. }
  6. export const CategoryEntity = new EntitySchema<Category>({
  7. name: "category",
  8. columns: {
  9. id: {
  10. type: Number,
  11. primary: true,
  12. generated: true
  13. },
  14. name: {
  15. type: String
  16. }
  17. }
  18. });

扩展架构

当使用Decorator方法时,很容易将基本列extend为抽象类并简单地扩展它。 例如,在BaseEntity中这样定义idcreatedAtupdatedAt列。 有关更多详细信息,请参阅具体表继承的文档

当使用EntitySchema方法时该方法便不可行。 但是,你可以使用Spread Operator(```)来改善。

重新审视上面的Category示例。 你可能希望extract基本列描述并在其他模式中复用它,则可以通过以下方式完成:

  1. import {EntitySchemaColumnOptions} from "typeorm";
  2. export const BaseColumnSchemaPart = {
  3. id: {
  4. type: Number,
  5. primary: true,
  6. generated: true,
  7. } as EntitySchemaColumnOptions,
  8. createdAt: {
  9. name: 'created_at',
  10. type: 'timestamp with time zone',
  11. createDate: true,
  12. } as EntitySchemaColumnOptions,
  13. updatedAt: {
  14. name: 'updated_at',
  15. type: 'timestamp with time zone',
  16. updateDate: true,
  17. } as EntitySchemaColumnOptions,
  18. };

现在你可以在其他模式模型中使用BaseColumnSchemaPart,如下所示:

  1. export const CategoryEntity = new EntitySchema<Category>({
  2. name: "category",
  3. columns: {
  4. ...BaseColumnSchemaPart,
  5. // CategoryEntity现在具有已定义的id,createdAt,updatedAt列!
  6. // 此外,还定义了以下新字段
  7. name: {
  8. type: String
  9. }
  10. }
  11. });

一定要将extended列添加到Category接口(例如,通过export interface Category extend Base Entity)。

使用Schemas查询/插入数据

当然,你可以像使用装饰器一样在存储库或实体管理器中使用已定义的模式。 回顾先前定义的Category示例(带有InterfaceCategoryEntity模式)以获取一些数据或操纵数据库。

  1. // 请求数据
  2. const categoryRepository = getRepository<Category>(CategoryEntity);
  3. const category = await categoryRepository.findOne(1); // category is properly typed!
  4. // 插入一条新category到数据库
  5. const categoryDTO = {
  6. // 注意id是自动生成的,请参考上面的架构定义。
  7. name: 'new category',
  8. };
  9. const newCategory = await categoryRepository.save(categoryDTO);