关联属性映射
如果实体或值对象的属性是一个实体,或者是一个元素类型为实体的某种形式的集合或数组,那么这么属性就称为关联属性。关联属性表明实体与另一个(或一组)外部实体之间存在某种形式的外部联系。
一、单值关联属性
单值关联属性有两种:
1. 多对一关联
多对一关联表明同一类型的多个实体都可以关联到不同(有时也可以是相同)类型的另一个实体上。典型例子是多个订单项OrderLine的product属性都可以关联到同一个Product的实例。反过来说,同一个Product可以出现在很多个OrderLine之中。
@Entity
@Table(name = "order_lines")
public class OrderLine extends BaseEntity {
@ManyToOne(optional = false)
@JoinColumn(name = "prod_id")
private Product product;
}
以上的例子中:
- 用
@ManyToOne逻辑注解标明这是一个多对一关联映射。多个OrderLine实体可以对应到一个Product实体。 @ManyToOne逻辑注解中的属性optional = false表明这个属性值不能为空。所有OrderLine实体都必须关联到一个而不是零个Product实体。@JoinColumn物理注解表明:在OrderLine实体所在的order_lines表中有一个外键列prod_id,指向Product实体所在的表的主键。这个注解可以忽略。此时默认的外键列名就是product_id。
2. 一对一关联
与多对一关联相比,一对一关联(OneToOne)相当少见。它要求两个不同类型的实体之间的一一对应关系。例如人力资源管理系统中,职务(Job)实体和职务说明书(JobDescription)之间的关系就是一对一关联关系。
一对一关联在后面的章节再详细讲述。
二、多值关联属性
多值关联属性有两种:
1. 一对多关联
一对多(OneToMany)关联是多对一关联的逆转方向。一对多关联是面向对象关系中“聚合(Aggregation)”关系的典型例子。与此相比,多值值属性是“组合(Composition)”关系的典型例子。
在本项目中,订单实体Order和订单项目OrderLine实体之间的关系就是(双向)一对多关系。
@Entity
@Table(name = "orders")
public class Order extends BaseEntity {
@OneToMany(mappedBy = "order", cascade = CascadeType.ALL, orphanRemoval = true)
@OrderColumn(name = "seq_no")
private List<OrderLine> lineItems = new ArrayList<>();
}
@Entity
@Table(name = "order_lines")
public class OrderLine extends BaseEntity {
@ManyToOne(optional = false)
private Order order;
}
以上例子中:
- 在
Order实体中,通过@OneToMany逻辑注解定义一个Order实体对一组OrderLine的聚合关系。换言之,一个订单包含一组订单项。 @OneToMany逻辑注解的mappedBy属性表明,由关联的另一端,也就是OrderLine实体来负责持久化关联关系(通过后者的order属性)。@OneToMany逻辑注解的cascade属性表明,当对Order实体执行各种持久化操作时,会级联持久化它所聚合的所有OrderLine。@OneToMany逻辑注解的orphanRemoval属性表明,当从订单的lineItems集合中移除某个OrderLine元素时,该OrderLine实体同时会从数据库中删除。- 这个一对多集合属性的类型是
List。List中的元素是有序的。@OrderColumn(name = "seq_no")物理注解指明了:在OrderLine实体所在的表order_lines中要定义一个数值型的列seq_no,用来存放列表元素的序号。
2. 多对多关联
多对多(ManyToMany)关联是一种双向关联关系。在严肃的项目中,多对多关系实际上是很少见的。多数时候应该将关联本身建模成为一个实体,从而将一个多对多关联变成从关联实体到另外两个实体的两个多对一关联。
多对多关联在后面的章节再详细讲述。