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);