当前位置: 首页 > 知识库问答 >
问题:

多对多Hibernate中覆盖的关系表数据

周睿范
2023-03-14

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

@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\u order relationship表,并将数据作为order和product中的主键插入。

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\u order)中的数据会被覆盖。被覆盖的记录是更新数量的记录。这是因为Hibernate正在从product\u order中删除记录,然后再次插入。我想要的是不更新product\u order表,因为它是不需要的。我只想在order表中插入一条记录,更新product表中的quantity,并在product\u order表中插入order\u id和product\u id。提前谢谢你。

共有2个答案

咸昊昊
2023-03-14

嗨,伙计们,我遇到了类似的情况,即使在维护了CascadeType之后。也许我的映射从映射表中丢失/覆盖,我学会了解决这个问题的艰难方法

我正在提供类似的场景,希望对一些人有所帮助。

我拿产品和订单来解释这个问题,并使用单向多目标映射

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

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

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

集合1--

集合2--

现在,当save set1 table product\u order\u映射如下所示

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

但是当在set1之后保存set2时,表product_order_映射将如下所示

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

我们可以看到保存set2映射之前和保存set2映射之后的区别p1-

当我们试图存储set2时,我们试图覆盖重复条目,如p1-

所以我们失去了一些先前的入口

避免从集合2中添加重复条目,如p1-

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);
}
}
}
}
萧业
2023-03-14

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

@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;
.......
}
 类似资料:
  • 问题内容: 我有实体类A和C。它们正在映射表tblA和tblC,并且它们之间具有多对多关系,而tblB可以在它们之间进行映射。tblB包含A_ID,C_ID和SetDate,最后一个是它的设置日期,因此是关系的属性。我的问题是,如何最好地映射此属性?目前,它们尚未映射,如下所示: A: C: 我应该如何从中获取tblB.SetDate? 干杯 问题答案: 据我所知, 不可能 以这种方式映射它,您必

  • 问题内容: 问题在标题中: 如何将多对多关系表作为实体? 问题答案: 我会说,你的问题很合理。看看这个文档部分:第24章最佳实践。摘录: 不要使用外来关联映射: 真正的多对多关联的实际测试案例很少见。大多数时候,您需要存储在“链接表”中的其他信息。在这种情况下,最好将两个一对多关联用于中间链接类。实际上,大多数关联是一对多和多对一的。因此,在使用任何其他关联样式时,您应谨慎进行。 我们正在处理的方

  • 我有两个类:< code>User和< code>UserProfile。 用户类别: 用户配置文件类: 当我使用此代码时,我在具有多对多关系的表用户配置文件中获得重复的实体。我使用 函数来保存对象。我做错了什么? 然后我删除 cascadeType,出现错误:对象引用未保存的瞬态实例 - 在刷新之前保存瞬态实例。 Hibernate日志:

  • 我试图使用Hibernate标准来选择,使用多对多关系中相关的表。n-m表有一些附加列,而不仅仅是每个表的ID。 java.lang.IllegalArgumentException:无法在此ManagedType[User]上找到具有给定名称[UserRolesList.Role]的属性 我已经为这种情况尝试了许多选择,比如加入,但仍然无法使其工作。

  • 我在hibernate中搜索建立关系的各种可能性,遇到了下面的代码片段

  • 如果在中只有一组,这将非常好地工作。ASSESSMENT_COMMENT只有两列: 它将完美地代表一对多的关系。 现在问题来了: 那么,1)这是Hibernate中已知的bug吗?2)有办法解决这个问题吗?我可以强制Hibernate创建两个映射表,每个映射表一个吗?请记住,我不能更改类来引用(业务逻辑需求)