休眠删除的对象将被级联重新保存

Posted

技术标签:

【中文标题】休眠删除的对象将被级联重新保存【英文标题】:Hibernate deleted object would be re-saved by cascade 【发布时间】:2017-09-15 02:07:18 【问题描述】:

我正在尝试在休眠中删除一个子实体,但出现此异常:

 org.hibernate.ObjectDeletedException: deleted object would be re-saved by cascade (remove deleted object from associations): [com.epic.ecommerce.core.model.Customer#newnameTest]
at org.hibernate.internal.SessionImpl.forceFlush(SessionImpl.java:1236)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:187)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.performSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:114)
at org.hibernate.event.internal.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:90)
at org.hibernate.internal.SessionImpl.fireSaveOrUpdate(SessionImpl.java:684)
at org.hibernate.internal.SessionImpl.saveOrUpdate(SessionImpl.java:676)
at org.hibernate.engine.spi.CascadingActions$5.cascade(CascadingActions.java:235)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:350)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:293)...

这些是我的实体:

@Entity

@Table(name="客户") 公共类客户

    @Id
    @Column(name="customer_id")
    @GeneratedValue(generator="gen")
    @GenericGenerator(name="gen", strategy="foreign",parameters=@Parameter(name="property", value="user"))
    private String id;

@OneToMany(cascade=CascadeType.ALL,mappedBy="customerId",orphanRemoval=true) 私有设置 quoteConfigs;

    public Set<QuoteConfiguration> getQuoteConfigs() 
    return quoteConfigs;
    

    public void setQuoteConfigs(Set<QuoteConfiguration> quoteConfigs) 
    this.quoteConfigs = quoteConfigs;
    


    public String getId() 
        return id;
    

    public void setId(String id) 
        this.id = id;
    

    @OneToOne
    @PrimaryKeyJoinColumn
    private User user;

    public User getUser() 
        return user;
    

    public void setUser(User user) 
        this.user = user;
    



@Entity
@Table(name="quote_configuration")
public class QuoteConfiguration implements java.io.Serializable

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "quote_id",unique = true, nullable = false)  
private Integer quoteId;

@Column(name = "base_product", nullable = false)
private String baseProduct;

@Column(name = "quote_name")
private String quoteName;   

/*
@Column(name = "customer_customer_id")
private String customerId;

public String getCustomerId() 
    return customerId;


public void setCustomerId(String customerId) 
    this.customerId = customerId;

*/
@ManyToOne(cascade=CascadeType.ALL) 
@JoinColumn(name = "customer_customer_id")
private Customer customerId;


public Customer getCustomerId() 
    return customerId;


public void setCustomerId(Customer customerId) 
    this.customerId = customerId;

这是我尝试删除的部分

    Session session = this.sessionFactory.getCurrentSession();
    Query q = session.createQuery("from QuoteConfiguration where quoteId = :quoteId ");
    q.setParameter("quoteId", quoteId);
    QuoteConfiguration quote = (QuoteConfiguration)q.list().get(0);

    Query qc=session.createQuery("from Customer where id=:id");
    qc.setParameter("id", quote.getCustomerId().getId());

    Customer customer=(Customer)qc.list().get(0);
    customer.getQuoteConfigs().remove(quote);
    session.delete(quote);
    session.save(customer);

我的问题是如何删除子实体 QuoteConfiguration,而不会在 Customer 中获得该关联异常。谢谢

【问题讨论】:

【参考方案1】:

只需从您的代码中删除 session.delete(quote)

您的@OneToMany 集合是您记录的,并且它已设置为删除孤立 元素。因此,当您执行customer.getQuoteConfigs().remove(quote) 时,它已经告诉 Hibernate 从数据库中删除记录。


附带说明,您应该尝试session.get(class, id),而不是使用 HQL 来获取单个实例。

您不需要save(customer),因为 Hibernate 始终跟踪持久化实例。它们将在交易关闭时自动保存(除非您的会话设置为手动,否则不应如此)。

【讨论】:

感谢 Guillaume F. 的回复,但仍然给了我同样的例外,您知道我可以通过其他方式删除这个孩子吗? 确保您的所有@OneToMany 和@ManyToOne 关系都设置为(fetch=FetchType.LAZY)loading。此外,请确认您的 Session 中没有加载其他集合。 看看这个帖子,有意思:***.com/questions/24257449/… 我做了另一个修复,更改了两个实体中的 fetchType 并更改了我的 DAO 中的删除

以上是关于休眠删除的对象将被级联重新保存的主要内容,如果未能解决你的问题,请参考以下文章

休眠级联删除期间的ConstraintViolationException

休眠:是不是可以仅在测试时“保存级联”?

休眠删除不会级联

休眠 - 多对多关系中的级联删除

休眠:分离没有级联到集合

保存对象上的休眠空指针