在领域驱动设计中,有一些结构主表和明细表必须一起显现才能表达业务意义,明细表不能单独使用被称为值对象,主表表达业务对象称为实体,也称为聚合根。
1. 在实体中的值对象上增加 @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个表
- sale_order 主表
- order_detail 明细表
- sale_order_order_detail_list 关系表
2. 增加 @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) 字段,并做了外键关联
3. 使用非主键做关联
在特殊场景下,不用主键id做,使用更有意义的order_code
@OneToMany @JoinColumn(name = "orderCode", referencedColumnName = "orderCode") private List<OrderDetail> orderDetailList;
name
为子表的关联属性
referencedColumnName
为主表的关联属性
注意: 使用此注解后,两个表没有自动建立外键依赖,且主表的order_code字段为建唯一索引
4. 执行写入操作时报错
问题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;
5. 相关代码
@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; }
原文
https://segmentfault.com/a/1190000021976159
本站部分文章源于互联网,本着传播知识、有益学习和研究的目的进行的转载,为网友免费提供。如有著作权人或出版方提出异议,本站将立即删除。如果您对文章转载有任何疑问请告之我们,以便我们及时纠正。PS:推荐一个微信公众号: askHarries 或者qq群:474807195,里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多

转载请注明原文出处:Harries Blog™ » 2. JPA对象关系映射–值对象映射