jpa使用@OneToMany注解进行两个表之间一对多的关联以方便级联查询。当需要对关联的表进行增删改操作的时候,需要根据实际需求选择合适的方法。
order表的模型,省略get和set。其中order和installment是一对多关系
Order.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| @Entity @Table(name = "order") @NamedQuery(name = "Order.findAll", query = "SELECT o FROM Order o") public class Order extends AbstractModel { /** * 主键 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /** * 订单号 */ @Column(name = "order_number") private String orderNumber; /** * 总价 */ @Column(name = "quoted_price") private BigDecimal quotedPrice; /** * 分期信息 */ @OneToMany(cascade = {CascadeType.REFRESH, CascadeType.PERSIST, CascadeType.MERGE}, fetch = FetchType.LAZY, orphanRemoval = true) @JoinColumn(name = "order_id") @Where(clause = "delete_flag = 1") private List<Installment> installments; /** * 删除状态 */ @Enumerated(EnumType.ORDINAL) @Column(name = "delete_flag") private Status status; ……
|
Installment.java
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
| @Entity @Table(name = "installment") @NamedQuery(name = "Installment.findAll", query = "SELECT o FROM Installment o") public class Installment extends AbstractModel { /** * 分期主键 */ @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; /** * 订单标识 */ @Column(name = "order_id") private Long orderId; /** * 分期金额 */ @Column(name = "quoted_price") private BigDecimal quotedPrice; /** * 删除标识 */ @Enumerated(EnumType.ORDINAL) @Column(name = "delete_flag") private Status status; ……
|
1. 被关联表的id不作为其他表的外键关联
如果被关联的表的id没有被其他表的外键关联,可以进行“全删全加”进行被关联表的进行增删改的操作。
fillingModifyPara
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| …… order.setOrderNumber(orderDTO.getOrderNumbber()); order.setQuotedPrice(orderDTO.getQuotedPrice()); List<InstallmentDTO> installmentDTOs = orderDTO.getInstallments(); List<Installment> installments = new ArrayList<>(); for (InstallmentDTO installmentDTO : installmentDTOs) { //可以写构造函数进行初始操作 Installment installment = new Installment(); installment.setOrderId();//修改操作,orderId由前端传入 installment.setQuotedPrice(installmentDTO.gettQuotedPrice()); installments.add(installment); } order.getInstallments().clear(); order.getInstallments().addAll(installments);
|
这种方法将原来关联的表的相关内容先物理删除,再将新的内容全部添加上去。优点是方便简单,没有冗余数据;缺点是被关联的表的id不能作为其他表的外键关联。这里注意不要对installment再定义一个对象后进行order.set的操作,这样会出现两个对象而报错,详情可以参看hb源码。
2. 被关联表的id可能还关联了一堆乱七八糟的东西
当被关联表的id可能还关联了一堆乱七八糟的东西的时候,就不能进行简单的“全删全加”操作来修改关联表的内容。这个时候的做法是现将从数据库中查出的联表信息全部逻辑删除(status设为无效),然后与传入的进行比对,id相同的将status设置为有效,并修改内容;传入的DTO中没有id的作为新增的加入。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| order.setOrderNumber(orderDTO.getOrderNumbber()); order.setQuotedPrice(quotationDTO.getQuotedPrice()); List<Installment> installments = orders.getInstallments(); List<InstallmentDTO> installmentDTOS = quotationDTO.getInstallmentList(); List<Installment> newInstallments = new ArrayList<>(); installments.forEach(installment -> {installment.setStatus(Status.INVALID);}); for (InstallmentDTO installmentDTO : installmentDTOS) { for (Installment installment : installments) { if (installment.getId().equals(installmentDTO.getId())) { installment.setStatus(Status.VALID); installment.setQuotedPrice(installmentDTO.getQuotedPrice()); installment.setOrderId(); } } if (installmentDTO.getId() == null) { Installment installment = new Installment(); installment.setOrderId(); installment.setQuotedPrice(installmentDTO.gettQuotedPrice()); newInstallments.add(newInstallment); } } installments.addAll(newInstallments); orders.setInstallments(installments);
|