建议 - 使用列表

建议使用 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);
}