使用实体构造函数
在内部,MikroORM
从不调用托管实体(通过 EntityManager
加载的实体)上的实体构造函数,因此你可以随意使用它。仅当你通过 new
运算符自己实例化类时(或使用 em.create()
创建新实体实例时),才会调用构造函数,因此在创建新实体时,这是一个方便的地方来请求你的数据。
¥Internally, MikroORM
never calls entity constructor on managed entities (those loaded via EntityManager
), so you are free to use it as you wish. The constructor will be called only when you instantiate the class yourself via new
operator (or when using em.create()
to create new entity instance), so it is a handy place to require your data when creating new entity.
例如,以下 Book
实体定义将始终需要设置 title
和 author
,但 publisher
是可选的:
¥For example following Book
entity definition will always require to set title
and author
, but publisher
will be optional:
@Entity()
export class Book {
@PrimaryKey()
id!: number;
@Property()
title: string;
@Property()
foo!: number;
@ManyToOne()
author: Author;
@ManyToOne()
publisher?: Publisher;
@ManyToMany({ entity: () => BookTag, inversedBy: 'books' })
tags = new Collection<BookTag>(this);
constructor(title: string, author: Author) {
this.title = title;
this.author = author;
}
}
现在你可以通过这种方式构建你的实体:
¥Now you can construct your entity this way:
const author = new Author();
const book = new Book('Foo', author);
构造函数参数也将由 em.create()
自动检测和尊重:
¥The constructor parameters will be automatically detected and respected by em.create()
too:
const author = new Author();
const book = em.create(Book, { title: 'Foo', author, foo: 123 });
这将从数据中提取 title
和 author
并将其传递给构造函数,并仅将其余部分(因此这里只有 foo
属性)分配给创建的实体。
¥This will extract title
and author
from the data and pass it to the constructor, and assign only the rest (so here only the foo
property) to the created entity.
构造函数参数推断基于实体属性名称工作。换句话说,你的参数需要与实体属性完全相同地调用。
¥Constructor parameter inference works based on the entity property names. In other words, your parameters need to be called exactly the same as entity properties.
构造函数中的 POJO 与实体实例
¥POJO vs entity instance in constructor
你可能很想用 DTO 定义构造函数,如下所示:
¥It might be tempting to just define your constructor with a DTO as follows:
constructor(dto: { title: string; author: number }) {
this.title = dto.title;
// fails to compile, `number` is assignable not `Author`!
this.author = dto.author;
}
存在多个自定义选项以允许更改样式或自定义逻辑。ORM 期望关系属性中有实体实例,仅此而已。
¥Similar (but more hidden) problem would appear if your dto.author
was a POJO (so an object, but not an instance of the Author
entity), as that might type check, although it won't work either. The ORM expects entity instances in relation properties, nothing else.
但不用担心,因为 v5.6 有一种简单的方法可以将主键转换为实体引用,即 rel()
助手:
¥But worry not, since v5.6 there is an easy way to convert a primary key to the entity reference, the rel()
helper:
@ManyToOne({ entity: () => Author })
author: Rel<Author>;
constructor(dto: { title: string; author: number }) {
this.title = dto.title;
this.author = rel(Author, dto.author);
}
rel()
助手将创建尚未管理的实体实例(因为我们没有向其传递任何 EntityManager
实例),但一旦它被管理,它将被视为现有实体引用。这实际上相当于 em.getReference()
,但没有手头的 EntityManager
实例。
¥The rel()
helper will create entity instance that is not yet managed (as we don't pass it any EntityManager
instance), but it will be considered as existing entity reference once it becomes managed. This is in fact an equivalent to em.getReference()
, but without having the EntityManager
instance at hand.
rel()
是Reference.createNakedFromPK()
的快捷方式。¥
rel()
is a shortcut forReference.createNakedFromPK()
.
如果你想要更安全并使用 Reference
封装器,ref()
助手也接受这个新签名:
¥And if you want to be safer and use the Reference
wrapper, the ref()
helper also accepts this new signature:
@ManyToOne({ entity: () => Author, ref: true })
author: Ref<Author>;
constructor(dto: { title: string; author: number }) {
this.title = dto.title;
this.author = ref(Author, dto.author);
}
rel
和 ref
助手将接受主键和实体实例以及空值(null
或 undefined
)。
¥The rel
and ref
helpers will accept both primary key and entity instance, as well as empty value (null
or undefined
).
book.author = ref(Author, null);
book.author = ref(Author, undefined);
book.author = ref(null);
book.author = ref(undefined);
book.author = ref(Author, 1);
book.author = ref(Author, author);
book.author = ref(author);
使用原生私有属性
¥Using native private properties
如果你想在实体内使用原生私有属性,MikroORM 通过 Object.create()
创建实体实例的默认方法不可行(有关此内容的更多信息,请参阅 issue)。要强制使用实体构造函数,你可以使用 forceEntityConstructor
切换。
¥If you want to use native private properties inside entities, the default approach of how MikroORM creates entity instances via Object.create()
is not viable (more about this in the issue). To force usage of entity constructors, you can use forceEntityConstructor
toggle.