【问题标题】:Relationship table data overwritten in many-to-many hibernate在多对多休眠中覆盖的关系表数据
【发布时间】:2018-04-27 23:27:37
【问题描述】:

我有两个具有多对多关系的实体类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 关系表,并将数据作为订单和产品的主键插入。

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();
 }
}'

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

【问题讨论】:

    标签: java hibernate many-to-many hibernate-mapping persistent


    【解决方案1】:

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

    @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;
    .......
    }
    

    【讨论】:

      【解决方案2】:

      大家好,我遇到了类似的情况,即使在维护 CascadeType.PERSIST 之后,我的映射仍然从映射表中丢失/覆盖 我学会了解决这个问题的艰难方法

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

      我正在使用产品和订单来解释问题并使用单向多对多映射

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

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

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

      现在让我们举一个在表中存储数据的实际示例

      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

      现在save set1表product_order_mapping的样子

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

      但是当在 set1 表 product_order_mapping 之后保存 set2 时会是这样的

      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 已经可用 在映射表中 所以发生的事情是在添加这些重复条目之前,所有与 p1 相关的映射都被删除,然后 p1->o1,p1->o2 被添加

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

      解决方案

      避免从 set2 添加重复条目,例如 p1->o1,p1->o2,因为它们已经存在于映射表中

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

      【讨论】:

        猜你喜欢
        • 2015-12-22
        • 2012-02-17
        • 1970-01-01
        • 1970-01-01
        • 2011-12-31
        • 2015-07-21
        相关资源
        最近更新 更多