gpt4 book ai didi

java - 使用 JpaRepository 更新实体中的列表项(保留主键)

转载 作者:行者123 更新时间:2023-12-02 10:20:23 24 4
gpt4 key购买 nike

最好用一个例子来提问,这样......

实体 PurchaseOrder有一个列表 PurchaseOrderDetailOneToMany关系。 Entitylist items无法直接保存使用的 JPA 方法,因为涉及一些计算。当我们对 PurchaseOrder 执行更新时我们必须保留主键,以便我们可以像这样更新

PurchaseOrder purchaseOrder = purchaseOrderRepository.getOne(purchaseOrderRequest.getId());
purchaseOrder.setSupplier(purchaseOrderRequest.getSupplier());
purchaseOrder.setDollarRate(purchaseOrderRequest.getDollarRate());
purchaseOrder.setShippingCost(purchaseOrderRequest.getShippingCost());
return purchaseOrderRepository.save(purchaseOrder);

但是如何Beautifully更新List<PurchaseOrderDetail> purchaseOrderDetails

我有以下代码,它将删除现有列表项并插入丢失主键的新项目。但是 JPA way 是什么?这样做,以便在更新期间发生以下情况

1. If some items were deleted they should be deleted from DB.
2. If some items were updated they should be updated preserving the primary keys.
3. If some new items are added they should be created having new primary keys.

代码

purchaseOrder.setPurchaseOrderDetails(null);

for (PurchaseOrderDetailRequest purchaseOrderDetailRequest : purchaseOrderRequest.getPurchaseOrderDetails())
{
PurchaseOrderDetail purchaseOrderDetail = new PurchaseOrderDetail();
purchaseOrderDetail.setPartNumber(purchaseOrderDetailRequest.getPartNumber());
purchaseOrderDetail.setDescription(purchaseOrderDetailRequest.getDescription());
purchaseOrderDetail.setQuantity(purchaseOrderDetailRequest.getQuantity());
purchaseOrderDetail.setUnitPriceInDollars(purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setTotalPriceInDollars(purchaseOrderDetailRequest.getQuantity() * purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setUnitPriceInSAR(purchaseOrder.getDollarRate() * purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setTotalPriceInSAR(purchaseOrderDetailRequest.getQuantity() * purchaseOrderDetail.getUnitPriceInSAR());
purchaseOrderDetail.setUnitCost(purchaseOrderDetail.getUnitPriceInSAR() + shippingFactor);
purchaseOrder.addPurchaseOrderDetail(purchaseOrderDetail);
}

采购订单

@Entity
@Table(name = "purchaseOrders")
public class PurchaseOrder extends UserDateAudit
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank
@Size(max = 140)
private String supplier;

@NotNull
private Float dollarRate;

@NotNull
private Float amount;

@NotNull
private Float shippingCost;

@OneToMany(
mappedBy = "purchaseOrder",
cascade = CascadeType.ALL,
fetch = FetchType.EAGER,
orphanRemoval = true
)
@Fetch(FetchMode.SELECT)
@BatchSize(size = 150)
private List<PurchaseOrderDetail> purchaseOrderDetails = new ArrayList<>();
}

采购订单详细信息

@Entity
@Table(name = "purchaseOrderDetails")
public class PurchaseOrderDetail
{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@NotBlank
@Size(max = 50)
private String partNumber;

@Size(max = 256)
private String description;

@NotNull
private Integer quantity;

@NotNull
private Float unitPriceInDollars;

@NotNull
private Float totalPriceInDollars;

@NotNull
private Float unitPriceInSAR;

@NotNull
private Float totalPriceInSAR;

@NotNull
private Float unitCost;

@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "purchaseOrder_id", nullable = false)
private PurchaseOrder purchaseOrder;
}

最佳答案

JpaRepository.save() 根据实体状态执行 em.persist()em.merge()
并且您还配置了 @OneToMany 关系与 cascade = CascadeType.ALLorphanRemoval = true 的映射,因此您的方式是正确的.
您需要在代码中执行的操作是更新 PurchaseOrder 中定义的列表的 PurchaseOrderDetail 元素,而不是为它们创建新实例。
如果需要,您可以在映射中添加现有元素以加快查找处理速度。

// collect existing details into a map to fast up
Map<Long, PurchaseOrderDetail> purchaseOrderDetailByIdMap =
purchaseOrder.getPurchaseOrderDetails()
.stream()
.collect(toMap(PurchaseOrderDetail::getId, p -> p);

//collect new details into a list
List<PurchaseOrderDetail> updatedDetails =
purchaseOrderRequest.getPurchaseOrderDetails()
.stream()
.map(detailReq -> mapDetailRequestToDetail(detailReq,
purchaseOrderDetailByIdMap))
.collect(toList());

// overwrite the relationship with the updatedDetails var
purchaseOrder.setPurchaseOrderDetails(updatedDetails);

// ...

// mapping function extracted to be clearer
private PurchaseOrderDetail mapDetailRequestToDetail(PurchaseOrderDetailRequest purchaseOrderDetailRequest,
Map<Long, PurchaseOrderDetail> purchaseOrderDetailByIdMap) {

// Here you get the existing element with the defined id or you create a new one
PurchaseOrderDetail purchaseOrderDetail =
purchaseOrderDetailByIdMap.computeIfAbsent(purchaseOrderDetailRequest.getId(), k-> new PurchaseOrderDetail());

// set fields
purchaseOrderDetail.setPartNumber(purchaseOrderDetailRequest.getPartNumber());
purchaseOrderDetail.setDescription(purchaseOrderDetailRequest.getDescription());
purchaseOrderDetail.setQuantity(purchaseOrderDetailRequest.getQuantity());
purchaseOrderDetail.setUnitPriceInDollars(purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setTotalPriceInDollars(purchaseOrderDetailRequest.getQuantity() * purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setUnitPriceInSAR(purchaseOrder.getDollarRate() * purchaseOrderDetailRequest.getUnitPriceInDollars());
purchaseOrderDetail.setTotalPriceInSAR(purchaseOrderDetailRequest.getQuantity() * purchaseOrderDetail.getUnitPriceInSAR());
purchaseOrderDetail.setUnitCost(purchaseOrderDetail.getUnitPriceInSAR() + shippingFactor);

return purchaseOrderDetail;
}

关于java - 使用 JpaRepository 更新实体中的列表项(保留主键),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54386667/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com