建议 - 使用列表
建议使用 List
映射 @OneToMany
或 @ManyToMany
的集合属性。
这意味着我们避免了使用 Set
时隐式使用 hashCode() / equals()
。
列表与集合
Hibernate 袋语义
使用 Hibernate 时,可能更倾向于使用 Set
,因为 Set 和 List 在 Hibernate 中具有不同的语义。Set 使用“袋语义”,通常更适合 Hibernate。
hashCode() / equals()
使用 Set 意味着隐式使用 hashCode()/equals()
实现。这是有问题的,因为实体 Bean 的本质是它们会发生变化,并且通常在 Bean 持久化之后才具有 @Id 值。
在实体 Bean 上实现 hashCode()/equals() 的难度意味着 List
是保存 @OneToMany 和 @ManyToMany 集合的推荐集合类型。
@Entity
@Table(name="customer")
public class Customer extends BaseModel {
...
// List is recommended for collection types
@OneToMany(mappedBy="customer", cascade=CascadeType.PERSIST)
List<Contact> contacts;
...
增强
定义集合类型增强时,将确保
- 删除任何 List/Set 初始化
- List/Set 始终由 Ebean 初始化(且永远不为 null)
删除 List/Set 初始化
// initialisation of the new ArrayList() is removed
@OneToMany(mappedBy="customer")
List<Contact> contacts = new ArrayList<Contact>;
// you can declare an un-initialised List if you wish
// and there is no actual difference to an initialised one
// because enhancement will always initialise it
@OneToMany(mappedBy="customer")
List<Contact> contacts;
在 Kotlin 中,我们通常希望始终将其定义为非 null
// kotlin: contacts type not nullable
@OneToMany(mappedBy = "customer")
var contacts: MutableList<Contact> = ArrayList()
List/Set 始终被初始化(永远不为 null)
Ebean 需要控制 List/Set 的初始化,以便支持
- 延迟加载
- 支持 @PrivateOwned,我们需要列表/集合知道删除
- 支持 @ManyToMany,我们需要列表/集合知道添加和删除
增强确保每当访问 List/Set 时,Ebean 始终会初始化它,并在必要时设置 List/Set 以侦听添加/删除(对于 @PrivateOwned 和 @ManyToMany)。
这会产生这样的效果:访问列表/集合时,它将始终不为 null。
// it "looks" like contacts could be null ...
@OneToMany(mappedBy="customer")
List<Contact> contacts;
public void addContact(Contact contact) {
// but actually contacts will never be null here
if (contacts == null) {
contacts = new ArrayList<>();
}
contacts.add(contact);
}
增强替换了所有 GETFIELD
指令,用于 持久集合
,并用确保在需要时初始化 List/Set 的代码替换了它。
@OneToMany(mappedBy="customer")
List<Contact> contacts;
public void addContact(Contact contact) {
// this is safe to write as contacts
// will never be null here
contacts.add(contact);
}