我们有一个名为Enterprise
的实体和一些引用和定义Enterprise
对象类型的实体,例如Subsidiary
,Carrier
,Agent
,Supplier
和Client
。每个Enterprise
对象可以是一种或多种类型。
今天我们有基于连接列的映射,这些映射由每个类型实体映射,例如在我们拥有的Supplier
上:
@Entity
public class Enterprise {
@Id
private Integer id;
...
@Column
private Boolean isSupplier;
...
}
@Entity
public class Supplier {
@Id
private Integer id;
@OneToOne(fetch=FetchType.LAZY)
@JoinColumn(name="IDENTERPRISE")
private Enterprise enterprise;
// Some other fields specific to suppliers here
...
}
其他实体遵循这种映射模型,但是由于延迟加载和其他问题而导致模型和关系持续存在问题,它变得难以维护并且导致混淆和更多映射问题,例如,假设我们有另一个名为Invoice
的实体,我们需要指定Client
和Carrier
,这里的一些程序员更喜欢与Enterprise
建立关系,然后使用字段值用于在服务类上找到正确的对象,其他程序员更喜欢直接与Client
或Carrier
建立关系,系统正在变成水果沙拉。
我知道@Embeddable
个实体,我知道这可能是最好的解决方案,但我们的数据库专家说要避免信息太多,字段太多的表格,这就是@Embeddable
原因。
也许继承是一个很好的解决方案,但我们不知道如何使用给定的方案来实现这一点,我们有Enterprise
可以是Client
和Supplier
但JPA需要一个识别对象类型的鉴别器列。
我们决定更改这些实体,并尽可能使用最佳映射策略。
我们在Jean Merelis的评论中找到了here¹,这是一个如何做@OneToOne
懒惰关系的例子,请参阅下面的英文来源:
public class Person {
@Id
private Long id;
@OneToOne(fetch=FetchType.LAZY, mappedBy="person")
@PrimaryKeyJoinColumn
private Address address;
}
public class Address {
@Id
private Long id;
@OneToOne(optional=false)
@MapsId
@JoinColumn(name="person_id", referencedColumnName="id")
private Person person;
}
通过这种方式,我们可以级联持久化操作并始终引用Enterprise
实体,提供如下字段:
@Entity
public class Enterprise {
@Id
private Integer id;
@OneToOne(mappedBy="enterprise", fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE})
@PrimaryKeyJoinColumn
private Supplier asSupplier;
...
}
@Entity
public class Supplier {
@Id
@Column(name="IDSUPPLIER")
private Integer id;
@OneToOne(optional=false)
@MapsId
@JoinColumn(name="IDENTERPRISE")
private Enterprise enterprise;
// Some other fields specific to suppliers here
...
}
所以,最后,我的问题,这是一个不错的选择吗?如果没有,你能提供一个如何做得更好的好例子吗?
¹:对不起葡萄牙语网站,但我没有找到这个例子的英文版。