关系 table 数据在多对多休眠中被覆盖

Relationship table data overwritten in many-to-many hibernate

我有两个实体 类 Order 和 Product 多对多关系(多个订单可能有相同的产品,只要库存不为空,一个订单可能包含多个产品)如下:

@Entity
@Table(name = "Order_")
public class Order implements Serializable {

    .......
@ManyToMany(mappedBy="orders")
private List<Product> products;  
    .......
}

@Entity
@Table(name = "Product")
public class Product implements Serializable {

.......
@ManyToMany
@JoinTable(name = "product_order", 
        joinColumns = { @JoinColumn(referencedColumnName="id") }, 
        inverseJoinColumns = { @JoinColumn(referencedColumnName="id") })
private List <Order> orders;
.......
}

以下是用于插入订单和产品的Dao。产品是预定义的,我只需要更新它们的数量。该订单将作为新订单插入。必须生成 product_order 关系 table 并将数据作为主键从订单和产品中插入。

public class OrderDao {

 public static void insertProductOrder(Order order, List <Product> cart, List<Integer> quantity){

    ...............
    session.beginTransaction();

    Query query;

    Product pr;

    List list;

    List <Order> orders = new ArrayList<>();
    orders.add(order);

    for(int i=0;i<cart.size();i++) {

    query = session.createQuery("from Product where id = :pid");
    query.setParameter("pid", cart.get(i).getId());
    list = query.list();
    pr = (Product) list.get(0);

    pr.setQuantity(cart.get(i).getQuantity() - quantity.get(i));

    cart.get(i).setOrders(orders);
    }

    order.setProducts(cart);

    session.save(order);

    session.getTransaction().commit();
 }
}'

在这种情况下,数据已正确插入到所有三个 table 中。但是当我尝试插入新订单时,关系 table 中的数据即 product_order 被覆盖。被覆盖的记录是正在更新数量的记录。这是因为 Hibernate 正在从 product_order 中删除记录,然后再次插入。我想要的是不需要 product_order table 的更新。我只想在订单 table 中插入一条记录,在产品 table 中更新数量并将 order_id 和 product_id 插入 product_order table .先感谢您。

通过正确识别所有者实体并进行如下更改使其正常工作:

@Entity
@Table(name = "Order_")
public class Order implements Serializable {
....... 
@ManyToMany
@Cascade({CascadeType.PERSIST})
@JoinTable(name = "product_order", 
        joinColumns = { @JoinColumn(referencedColumnName="id") }, 
        inverseJoinColumns = { @JoinColumn(referencedColumnName="id") })
private List<Product> products;
.......
}


@Entity
@Table(name = "Product")
public class Product implements Serializable {
.......
@Cascade({CascadeType.PERSIST})
@ManyToMany(mappedBy="products")
private List <Order> orders;
.......
}

大家好,我遇到了类似的情况,即使在维护 CascadeType.PERSIST 之后,我的映射仍从映射 table 中获取 lost/overridden 我学会了解决这个问题的艰难方法

我提供了类似的场景,希望对某些人有所帮助。

我正在使用 Product 和 Order 来解释问题并使用单向多对多映射

@Entity
@Table(name="Product")
public class Product {

    @Id
    @Column(name = "id")
    private Long id;

    
    @Column(name = "product")
    private String product;

    @ManyToMany(cascade = CascadeType.PERSIST,fetch= FetchType.EAGER)
    @JoinTable(name = "product_order_mapping", joinColumns = { @JoinColumn(name = "product_id") }, inverseJoinColumns = {
            @JoinColumn(name = "order_id") })
    @JsonProperty("orders")
    private Set<Order> orders =new HashSet<Order>();

    //setters and getters


}

@Table(name="Order")
public class Order {

    @Id
    @Column(name = "id")
    private Long id;
        
    @Column(name = "order")
    private String order;

    //setters and getters
    //equals and hashcode

}

实现逻辑

productList 和 OrderFunctions 是一些包含产品列表和订单详细信息的列表

for (Product pEntity : productList) {

OrderFunctions = this.getAllLineFunctions(product.getId(), cmEntity.getId())
                        .getBody();
Set<Order> oList = new HashSet<>();

for (OrderFunction orderFn : OrderFunctions) {
Order orderEntity = new Order();
orderEntity.setId(lfs.getOrderFunction_id());
orderEntity.setStageGroup(lfs.getOrderFunctionOrder());
oList.add(sgEntity);
}

orderRepository.saveAll(oList);
pEntity.setOrders(oList);
productRepository.save(pEntity);
}
}

为了理解重复映射让我们举个例子

假设产品属于公司 现在一个公司有多个产品 并且产品有多个订单

现在让我们以tables

存储数据为例

set1--> id 为 c1 的公司有 id 为 p1、p2、p3 的产品 产品 p1 的订单为 o1,o2,o3 产品 p2 的订单为 o1,o2 产品 p3 的订单为 o2,o3,o4

set2--> id 为 c2 的公司有 id 为 p1,p3 的产品 产品 p1 的订单为 o1,o2 产品 p3 的订单为 o2

现在保存set1时tableproduct_order_mapping看起来像

product_id  order_id
---------------------
   p1         o1
   p1         o2
   p1         o3
   p2         o1
   p2         o2
   p3         o2
   p3         o3
   p3         o4

但是在set1之后保存set2时table product_order_mapping会像

product_id  order_id
---------------------
   p1         o1
   p1         o2
   p2         o1
   p2         o2
   p3         o2

我们可以看到保存set2之前和保存set2之后的区别 映射 p1->o3 、 p3->o3 和 p3->o4 丢失

丢失映射的原因

当我们试图存储 set2 时,我们试图覆盖像 p1->o1、p1->o2 这样的重复条目,它们都已经可用 在映射中 table 所以发生的事情是在添加这些重复条目之前删除所有与 p1 相关的映射然后 添加了 p1->o1,p1->o2

所以我们丢失了一些以前的条目

解决方案

避免添加来自 set2 的重复条目,如 p1->o1、p1->o2,因为它们已经存在于映射 table

for (Company cEntity : companyList) {
for (Product pEntity : productList) {

OrderFunctions = this.getAllOrderFunctions(cEntity.getId(), pEntity.getId());
                        
Set<Order> oList = new HashSet<>();

for (OrderFunction orderFn : OrderFunctions) {
Order orderEntity = new Order();
orderEntity.setId(lfs.getOrderFunction_id());
orderEntity.setStageGroup(lfs.getOrderFunctionOrder());
oList.add(sgEntity);
}

Set<Order> collectSG = pEntity.getOrders().stream().filter(o->oList.contains(o)).collect(Collectors.toSet());
oList.removeAll(collectSG);
if(oList.size()>0) {
orderRepository.saveAll(oList);
                
pEntity.setOrders(oList);
productRepository.save(pEntity);
}
}
}
}