关系 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);
}
}
}
}
我有两个实体 类 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);
}
}
}
}