当父项在同一事务中更新时,Hibernate 删除子项
Hibernate delete child when parent is getting updated in same transaction
我在我的域模型中定义了两个实体 Customer 和 SalesOrder,它们具有从客户到 salesOrder 的一对多关系。
下面的代码删除销售订单:
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
Iterator<SalesOrder> iter = customer.getSalesOrders().iterator();
while(iter.hasNext()){
SalesOrder order = iter.next();
if(order.getId().equals(salesOrder.getId())){
iter.remove();
break;
}
}
customerRepository.save(customer);
但是下面的代码并没有删除销售订单。
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
salesOrderRepository.delete(salesOrder);
customerRepository.save(customer);
以下是域 类:
Customer.java
@Entity
@Table(name = "customer", uniqueConstraints = { @UniqueConstraint(columnNames = { "code" }) })
public class Customer extends BaseEntity {
@Column
private String code;
@Column
private String name;
@Column
private String address;
@Column
private String phone1;
@Column
private String phone2;
@Column
private Double creditLimit;
@Column
private Double currentCredit;
@OneToMany(cascade=CascadeType.ALL,mappedBy="customer",fetch=FetchType.LAZY,orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<SalesOrder> salesOrders = new ArrayList<SalesOrder>();
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the address
*/
public String getAddress() {
return address;
}
/**
* @param address the address to set
*/
public void setAddress(String address) {
this.address = address;
}
/**
* @return the phone1
*/
public String getPhone1() {
return phone1;
}
/**
* @param phone1 the phone1 to set
*/
public void setPhone1(String phone1) {
this.phone1 = phone1;
}
/**
* @return the phone2
*/
public String getPhone2() {
return phone2;
}
/**
* @param phone2 the phone2 to set
*/
public void setPhone2(String phone2) {
this.phone2 = phone2;
}
/**
* @return the creditLimit
*/
public Double getCreditLimit() {
return creditLimit;
}
/**
* @param creditLimit the creditLimit to set
*/
public void setCreditLimit(Double creditLimit) {
this.creditLimit = creditLimit;
}
/**
* @return the currentCredit
*/
public Double getCurrentCredit() {
return currentCredit;
}
/**
* @param currentCredit the currentCredit to set
*/
public void setCurrentCredit(Double currentCredit) {
this.currentCredit = currentCredit;
}
/**
* @return the salesOrders
*/
public List<SalesOrder> getSalesOrders() {
return salesOrders;
}
/**
* @param salesOrders the salesOrders to set
*/
public void setSalesOrders(List<SalesOrder> salesOrders) {
this.salesOrders = salesOrders;
}
}
SalesOrder.java
@Entity
@Table(name = "sales_order", uniqueConstraints = { @UniqueConstraint(columnNames = { "orderNumber" }) })
public class SalesOrder extends BaseEntity {
@Column
private String orderNumber;
@ManyToOne(cascade=CascadeType.DETACH, fetch=FetchType.LAZY)
@JoinColumn(name="customer_id",referencedColumnName="id")
private Customer customer;
@Column
private Double totalPrice;
@OneToMany(cascade=CascadeType.ALL,mappedBy="salesOrder",fetch=FetchType.LAZY,orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<OrderLines> orderLines= new ArrayList<OrderLines>();
/**
* @return the orderNumber
*/
public String getOrderNumber() {
return orderNumber;
}
/**
* @param orderNumber the orderNumber to set
*/
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
/**
* @return the customer
*/
public Customer getCustomer() {
return customer;
}
/**
* @param customer the customer to set
*/
public void setCustomer(Customer customer) {
this.customer = customer;
}
/**
* @return the totalPrice
*/
public Double getTotalPrice() {
return totalPrice;
}
/**
* @param totalPrice the totalPrice to set
*/
public void setTotalPrice(Double totalPrice) {
this.totalPrice = totalPrice;
}
/**
* @return the orderLines
*/
public List<OrderLines> getOrderLines() {
return orderLines;
}
/**
* @param orderLines the orderLines to set
*/
public void setOrderLines(List<OrderLines> orderLines) {
this.orderLines = orderLines;
}
}
请分享你的豆子。
根据您的描述,我希望您应该有:
@Entity
@Table(name="CUSTOMER")
public class Customer implements Serializable {
private static final long serialVersionUID = -4505027246487844609L;
@Id
private String username;
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
@JoinColumn(name="ORDER_USERNAME", nullable = false)
private List<SalesOrder> salesOrders;
}
重要的部分是:
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
获取类型是急切的,但也可能是惰性的,没有关于您如何获取链接实体数据的详细信息。
这应该可以解决问题,因此,如果您从父客户中删除销售额,它将被删除。
确认你的bean大致是这样的结构后,我们就可以继续分析你的问题了。
UPDATE 如果 bean 的结构是这样的,那么行为的原因就很清楚了。
当您获取 "Customer" 时,您已加载相关销售的集合...
现在.. 你在另一个对象中加载链接到该客户的销售,但 object1(客户)和 object2(销售)现在完全分开了..
结果是,当您删除 object2 时,您实际上执行了一次删除,但随后您保存了客户(其中仍然存在对您在列表对象中删除的销售的引用),它将 update/insert 所有链接到的销售基于客户 bean 的客户。
您的情况是:
将具有 Sales1 和 Sales2 的客户提取到 Object1 中
Sales1 提取到 Object2
删除 Object2,它会删除 sales1.. 这不会改变 Object1 的内容,它仍然会有一个与 sales1 和 sales2 相关联的客户
保存 Object1,您将更新客户(因为它已经存在),您将更新 sales2(因为它已经存在)并插入 sales1(因为您通过之前的删除删除了它)。
它将全部在同一个事务中干净地处理..
现在..如果你想达到你的结果,要么你"reload"(再做一个findOne或其他)删除相关销售后的bean客户,要么直接在销售集合上工作包含在客户 bean 中,以防万一从集合中删除这些对象并在完成后保存客户对象,而不涉及未链接到客户的辅助对象,这只会弄乱整个流程..
希望对您有所帮助。
我在我的域模型中定义了两个实体 Customer 和 SalesOrder,它们具有从客户到 salesOrder 的一对多关系。 下面的代码删除销售订单:
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
Iterator<SalesOrder> iter = customer.getSalesOrders().iterator();
while(iter.hasNext()){
SalesOrder order = iter.next();
if(order.getId().equals(salesOrder.getId())){
iter.remove();
break;
}
}
customerRepository.save(customer);
但是下面的代码并没有删除销售订单。
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
SalesOrder salesOrder = salesOrderRepository.findByOrderNumber(orderNumber);
if(null != salesOrder){
Customer customer = salesOrder.getCustomer();
customer.setCurrentCredit(customer.getCurrentCredit() - salesOrder.getTotalPrice());
salesOrderRepository.delete(salesOrder);
customerRepository.save(customer);
以下是域 类: Customer.java
@Entity
@Table(name = "customer", uniqueConstraints = { @UniqueConstraint(columnNames = { "code" }) })
public class Customer extends BaseEntity {
@Column
private String code;
@Column
private String name;
@Column
private String address;
@Column
private String phone1;
@Column
private String phone2;
@Column
private Double creditLimit;
@Column
private Double currentCredit;
@OneToMany(cascade=CascadeType.ALL,mappedBy="customer",fetch=FetchType.LAZY,orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<SalesOrder> salesOrders = new ArrayList<SalesOrder>();
/**
* @return the code
*/
public String getCode() {
return code;
}
/**
* @param code the code to set
*/
public void setCode(String code) {
this.code = code;
}
/**
* @return the name
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
/**
* @return the address
*/
public String getAddress() {
return address;
}
/**
* @param address the address to set
*/
public void setAddress(String address) {
this.address = address;
}
/**
* @return the phone1
*/
public String getPhone1() {
return phone1;
}
/**
* @param phone1 the phone1 to set
*/
public void setPhone1(String phone1) {
this.phone1 = phone1;
}
/**
* @return the phone2
*/
public String getPhone2() {
return phone2;
}
/**
* @param phone2 the phone2 to set
*/
public void setPhone2(String phone2) {
this.phone2 = phone2;
}
/**
* @return the creditLimit
*/
public Double getCreditLimit() {
return creditLimit;
}
/**
* @param creditLimit the creditLimit to set
*/
public void setCreditLimit(Double creditLimit) {
this.creditLimit = creditLimit;
}
/**
* @return the currentCredit
*/
public Double getCurrentCredit() {
return currentCredit;
}
/**
* @param currentCredit the currentCredit to set
*/
public void setCurrentCredit(Double currentCredit) {
this.currentCredit = currentCredit;
}
/**
* @return the salesOrders
*/
public List<SalesOrder> getSalesOrders() {
return salesOrders;
}
/**
* @param salesOrders the salesOrders to set
*/
public void setSalesOrders(List<SalesOrder> salesOrders) {
this.salesOrders = salesOrders;
}
}
SalesOrder.java
@Entity
@Table(name = "sales_order", uniqueConstraints = { @UniqueConstraint(columnNames = { "orderNumber" }) })
public class SalesOrder extends BaseEntity {
@Column
private String orderNumber;
@ManyToOne(cascade=CascadeType.DETACH, fetch=FetchType.LAZY)
@JoinColumn(name="customer_id",referencedColumnName="id")
private Customer customer;
@Column
private Double totalPrice;
@OneToMany(cascade=CascadeType.ALL,mappedBy="salesOrder",fetch=FetchType.LAZY,orphanRemoval = true)
@LazyCollection(LazyCollectionOption.FALSE)
private List<OrderLines> orderLines= new ArrayList<OrderLines>();
/**
* @return the orderNumber
*/
public String getOrderNumber() {
return orderNumber;
}
/**
* @param orderNumber the orderNumber to set
*/
public void setOrderNumber(String orderNumber) {
this.orderNumber = orderNumber;
}
/**
* @return the customer
*/
public Customer getCustomer() {
return customer;
}
/**
* @param customer the customer to set
*/
public void setCustomer(Customer customer) {
this.customer = customer;
}
/**
* @return the totalPrice
*/
public Double getTotalPrice() {
return totalPrice;
}
/**
* @param totalPrice the totalPrice to set
*/
public void setTotalPrice(Double totalPrice) {
this.totalPrice = totalPrice;
}
/**
* @return the orderLines
*/
public List<OrderLines> getOrderLines() {
return orderLines;
}
/**
* @param orderLines the orderLines to set
*/
public void setOrderLines(List<OrderLines> orderLines) {
this.orderLines = orderLines;
}
}
请分享你的豆子。 根据您的描述,我希望您应该有:
@Entity
@Table(name="CUSTOMER")
public class Customer implements Serializable {
private static final long serialVersionUID = -4505027246487844609L;
@Id
private String username;
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
@JoinColumn(name="ORDER_USERNAME", nullable = false)
private List<SalesOrder> salesOrders;
}
重要的部分是:
@OneToMany(cascade=CascadeType.ALL, orphanRemoval=true, fetch=FetchType.EAGER)
获取类型是急切的,但也可能是惰性的,没有关于您如何获取链接实体数据的详细信息。 这应该可以解决问题,因此,如果您从父客户中删除销售额,它将被删除。
确认你的bean大致是这样的结构后,我们就可以继续分析你的问题了。
UPDATE 如果 bean 的结构是这样的,那么行为的原因就很清楚了。 当您获取 "Customer" 时,您已加载相关销售的集合... 现在.. 你在另一个对象中加载链接到该客户的销售,但 object1(客户)和 object2(销售)现在完全分开了.. 结果是,当您删除 object2 时,您实际上执行了一次删除,但随后您保存了客户(其中仍然存在对您在列表对象中删除的销售的引用),它将 update/insert 所有链接到的销售基于客户 bean 的客户。
您的情况是: 将具有 Sales1 和 Sales2 的客户提取到 Object1 中 Sales1 提取到 Object2 删除 Object2,它会删除 sales1.. 这不会改变 Object1 的内容,它仍然会有一个与 sales1 和 sales2 相关联的客户 保存 Object1,您将更新客户(因为它已经存在),您将更新 sales2(因为它已经存在)并插入 sales1(因为您通过之前的删除删除了它)。 它将全部在同一个事务中干净地处理..
现在..如果你想达到你的结果,要么你"reload"(再做一个findOne或其他)删除相关销售后的bean客户,要么直接在销售集合上工作包含在客户 bean 中,以防万一从集合中删除这些对象并在完成后保存客户对象,而不涉及未链接到客户的辅助对象,这只会弄乱整个流程..
希望对您有所帮助。