【问题标题】:Hibernate detached entity error while removing an entity移除实体时休眠分离实体错误
【发布时间】:2017-04-18 09:12:32
【问题描述】:

根据here,只要我使用org.hibernate.Session 而不是JPA,就应该允许使用session.remove(entity) 删除分离的实体

但是,每当我尝试删除实体时,由于处于分离状态,它不允许我将其删除。

线条是这样的;

employeeDao.delete(employee)

即使我尝试像这样删除

employeeDao.delete(employeeDao.findById(employee.getId)):

它给出了同样的错误并且没有删除它。

例外是

意外的运行时异常 最后一个原因:删除一个分离的实例 rd.core.model.Employee#69

堆栈跟踪是

根本原因:

java.lang.IllegalArgumentException:删除分离的实例 rd.core.model.Employee#69 在 org.hibernate.jpa.event.internal.core.JpaDeleteEventListener.performDetachedEntityDeletionCheck(JpaDeleteEventListener.java:69) 在 org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:106) 在 org.hibernate.event.internal.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:73) 在 org.hibernate.internal.SessionImpl.fireDelete(SessionImpl.java:920) 在 org.hibernate.internal.SessionImpl.delete(SessionImpl.java:896) 在 rd.core.persistence.AbstractHibernateDao.delete(AbstractHibernateDao.java:35) 在 rd.core.services.EmployeeManagerImpl.deleteEmployee(EmployeeManagerImpl.java:186) 在 com.google.inject.persist.jpa.JpaLocalTxnInterceptor.invoke(JpaLocalTxnInterceptor.java:66) 在 java.lang.reflect.Method.invoke(Method.java:606)

我认为我搞砸了一些完全错误的事情。即使这会导致相同的异常。

 public void remove(Employee employee) {
        getCurrentSession().merge(employee);
        getCurrentSession().delete(employee);
    }

这是我的 POJO

@Entity
@Table(name = "TMP_EMPLOYEE")
public class Employee implements Identifiable<Integer> {

private static final String ID_GENERATOR_NAME = "TMP_EMPLOYEE_ID_SEQ";
public static final String PROP_FULL_NAME = "fullName";
public static final String PROP_ID = "id";
public static final String PROP_DEP = "department";

public static final String COLUMN_FULL_NAME = "FULL_NAME";
public static final String COLUMN_ID = "emp.ID";
public static final String COLUMN_DEP = "NAME";

@Column(name = "ID", nullable = false)
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = ID_GENERATOR_NAME)
@SequenceGenerator(name = ID_GENERATOR_NAME, sequenceName = "S_EMPLOYEE_ID", allocationSize = 1)
private Integer id;

@Column(name = "FULL_NAME", nullable = false, length = 60)
@Basic
private String fullName;

@ManyToOne
@JoinColumn(name = "DEP_ID", referencedColumnName ="ID", nullable = false)
@Fetch(FetchMode.SELECT)
private Department department;

public Integer getId() {
    return id;
}

public void setId(Integer id) {
    this.id = id;
}

public String getFullName() {
    return fullName;
}

public void setFullName(String fullName) {
    this.fullName = fullName;
}

public Integer getDepartmentId() {
    return 0;
}

public void setDepartmentId(Integer departmentId) {

}

@Override
public boolean equals(Object o) {
    if (this == o)
        return true;
    if (!(o instanceof Employee))
        return false;

    Employee that = (Employee) o;

    if (getId() != null ? !getId().equals(that.getId()) : that.getId() != null)
        return false;

    return true;
}

@Override
public int hashCode() {
    return getId() != null ? getId().hashCode() : 0;
}

@Override
public Integer getIdentity() {
    return id;
}

@Override
public String toString(){
    return "Id: " + this.id + " Employee Name: " + this.fullName;
}

public Department getDepartment() {
    return department;
}

public void setDepartment(Department department) {
    this.department = department;
}

这听起来可能很简单,但究竟是什么原因导致这样的实体状态发生变化,为什么即使它已分离,我也不能将其删除?

注意:我通过类委派同一个员工实例。所以它总是同一个实体。

如果您需要更多数据,请索取。我实际上不知道哪些数据可以帮助弄清楚这一点。

【问题讨论】:

  • 什么是错误?
  • 如果 hibernate 告诉你你的实体已经分离,在删除它之前尝试重新附加它。
  • 请展示你的pojo
  • 我已经添加了 Exception、StackTrace 和 POJO
  • 您确定将查找/删除序列包装在事务中吗? find 可能在事务之外,所以 find 将返回内存中保存的分离对象的状态

标签: java hibernate


【解决方案1】:

您可以阅读有关“why can't I remove it even if it is detached”的信息,在那里您可以找到:

需要注意的是,Hibernate 本身可以处理删除 分离状态。然而,JPA 不允许这样做。这里的含义是 将实体实例传递给 org.hibernate.Session 删除 方法可以处于托管或分离状态,而实体 在 javax.persistence.EntityManager 上传递给删除的实例必须是 处于托管状态。

关于为什么对象在您find 之后立即分离,我们在没有看到代码的情况下也不知道它。但是您可以在上面的同一篇文章中阅读有关实体如何分离以及如何在 3.8 节中重新附加它的信息。处理分离的数据

总结一下你应该不要做以防止对象分离是:

  1. 关闭持久化上下文
  2. 清除持久性上下文
  3. 从持久性上下文中逐出特定实体
  4. 对象序列化(反序列化对象将被分离,序列化对象并非总是如此)

但是,如果您无法阻止这种情况,您应该使用 Session.saveOrUpdate()、Session.update() 或 Session.merge() 之类的方法重新附加对象。或者..简单地使用hibernate的(不是JPA)Session.delete()。

【讨论】:

  • 你是对的。在 find 方法中,我使用的是查询而不是 session.get。所以它正在关闭持久性上下文并打开另一个。我猜是那件事?
【解决方案2】:

这是 Hibernate 的实体生命周期。所以 session.update 应该可以重新附加分离的实体。但是,更新可能会导致一些错误,所以我看到人们通常使用合并来重新附加实体。

所以如果你懒惰地初始化你的实体,它可能是相关的。

Hibernate 从数据库中读取数据时,数据保存在 会议。您可以保存对数据的引用 - 例如在您的 HTTP 请求。一旦事务被提交并且会话被 关闭您无法使用此会话加载任何进一步的数据。休眠 仅加载第一个对象并替换其他对象的集合 通过代理。如果访问代理,Hibernate 使用当前 会话初始化代理并从 数据库。

据我了解,您使用的是 Open-Session-in-View 模式。因此,请尝试阅读这些材料。

Lazy Initialization

Open Session In View

问题可能是由多种原因引起的,所以你做什么真的很重要。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多