在领域驱动设计中,有一些结构主表和明细表必须一起显现才能表达业务意义,明细表不能单独使用被称为值对象,主表表达业务对象称为实体,也称为聚合根。
@OneToMany
注解@Data @Entity public class SaleOrder { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer orderId; /** * 订单号 */ private String orderCode; /** * 交易金额 */ private BigDecimal tradeAmount; /** * 销售时间 */ private Date saleTime; /** * 订单状态 */ private String orderState; /** * 订单明细 */ @OneToMany private List<OrderDetail> orderDetailList; } @Entity @Data public class OrderDetail { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer orderDetailId; /** * 产品编码 */ private String productCode; /** * 数量 */ private Integer quantity; /** * 售价 */ private BigDecimal salePrice; /** * 折扣 */ private BigDecimal discount; } 复制代码
*运行后从数据库上看,形成3个表
@JoinColumn
注解,去掉关系表@OneToMany @JoinColumn private List<OrderDetail> orderDetailList; 复制代码
明细表结构:
Table: order_detail Columns: order_detail_id int(11) AI PK discount decimal(19,2) product_code varchar(255) quantity int(11) sale_price decimal(19,2) order_detail_list_order_id int(11)
从结构上讲自动增加了一个order_detail_list_order_id int(11) 字段,并做了外键关联
在特殊场景下,不用主键id做,使用更有意义的order_code
@OneToMany @JoinColumn(name = "orderCode", referencedColumnName = "orderCode") private List<OrderDetail> orderDetailList; 复制代码
name
为子表的关联属性
referencedColumnName
为主表的关联属性
注意: 使用此注解后,两个表没有自动建立外键依赖,且主表的order_code字段为建唯一索引
问题1: fun.barryhome.jpa.domain.SaleOrder cannot be cast to java.io.Serializable
原因: Hibernate有二级缓存,缓存会将对象写进硬盘,就必须序列化。
解决方法:
public class SaleOrder implements Serializable { ... } 复制代码
问题2: object references an unsaved transient instance - save the transient instance before flushing: fun.barryhome.jpa.domain.OrderDetail
原因: 当子对象不存在时,保存主对象时,必须级联保存子对象
解决方法:
@OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinColumn(name = "saleOrderCode", referencedColumnName = "orderCode") private List<OrderDetail> orderDetailList; 复制代码
@Data @Entity @Builder public class SaleOrder implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer orderId; /** * 订单号 */ private String orderCode; /** * 交易金额 */ private BigDecimal tradeAmount; /** * 销售时间 */ private Date saleTime; /** * 订单状态 */ private String orderState; /** * 订单明细 */ @OneToMany(cascade = {CascadeType.MERGE, CascadeType.PERSIST}) @JoinColumn(name = "saleOrderCode", referencedColumnName = "orderCode") private List<OrderDetail> orderDetailList; } @Entity @Data @Builder public class OrderDetail { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer orderDetailId; /** * 产品编码 */ private String productCode; /** * 数量 */ private Integer quantity; /** * 售价 */ private BigDecimal salePrice; /** * 折扣 */ private BigDecimal discount; } 复制代码