如何避免传递的分离实体在JPA中持续存在?

时间:2018-03-09 11:04:08

标签: java jpa

我在构建应用程序时遇到此错误:

Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: model.Student
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124) [hibernate-core-5.0.7.Final.jar:5.0.7.Final]
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58) [hibernate-core-5.0.7.Final.jar:5.0.7.Final]
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775) [hibernate-core-5.0.7.Final.jar:5.0.7.Final]
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748) [hibernate-core-5.0.7.Final.jar:5.0.7.Final]
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753) [hibernate-core-5.0.7.Final.jar:5.0.7.Final]
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146) [hibernate-entitymanager-5.0.7.Final.jar:5.0.7.Final]
    ... 190 more

我必须补充说,当我使用merge(std)而不是persist(std)时。比我没有问题,这也很奇怪。

这是我的实体类与GeneratedValue - > GenerationType.AUTO):

@Entity
@NamedQueries({@NamedQuery(name = Student.QRY_GET_STUDENTS, query = "select s from Student s")})
public class Student {

    public static final String QRY_GET_STUDENTS = "studentQuery";

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    @Size(min = 3, max = 70)
    private String name;

    @Size(min = 7, max = 7, message = "Matrikelnummer muss 7 Ziffern haben!")
    private String matriculationNumber;

    @DecimalMax(value = "5.0", message = "Note muss zwischen 1.0 und 5.0 sein!")
    private double note;

    private String lecture;
}

这就是我的持久性等级

@Stateless
@Transactional
public class StudentPersistence {

    @PersistenceContext(unitName = "UniPortalDS")
    private EntityManager em;

    public List<Student> getStudent() {
        return (List<Student>) em.createNamedQuery("studentQuery").getResultList();
    }

public List<Student> saveAllStudentsPersistence(@Nonnull Student std) {
        TypedQuery<Student> q = em.createNamedQuery(std.QRY_GET_STUDENTS, Student.class);
        em.persist(std);
        return q.getResultList();
    }
}

最后是我的服务类

@Stateless
public class StudentService {

    @EJB
    private StudentPersistence studentPersistence;

    public List<Student> getStudent() {
        return studentPersistence.getStudent();
    }

    //Jetzt -->
    public void saveStudentsNew(@Nonnull Student std) {
        studentPersistence.saveAllStudentsPersistence(std);
    }
}

1 个答案:

答案 0 :(得分:0)

在JPA中,“非持久性”和“分离式”不是一回事:

  • 非持久性:数据库中当前不存在这些实体。您可以使用非持久性实体,在其上调用persist(),这应该使其持久化(即将其存储在数据库中)。

  • 分离:这些实体确实存在于数据库中,但目前尚未被EntityManager管理。 persist()它们没有任何意义,因为虽然它们目前是分离的,但它们已经是持久性的,我认为这是Hibernate与您沟通的错误。但是,您可以merge()它们,即将它们与持久性上下文同步并将它们转换为EntityManager管理的实体,以便将更改发送到DB(1)。

    < / LI>

(1)实际上,merge()并未将实体从分离转换为托管;它所做的是将某个实体置于它所处的任何状态,并返回一个相应的托管实例。原始实例保持原状。