如何使用JPA和实体对象生命周期

时间:2015-11-01 17:02:15

标签: java jpa entity eclipselink

我正在使用JPA Eclipselink开发一个简单的Surveysystem,我在这方面很新(JPA和数据库),所以我不确定应采取哪种方法。

到目前为止,我所做的事情是使用DAO类来处理所有数据库逻辑,并且(希望)正确地注释所有实体关系。

我的教师实体可以进行多次调查,每个调查实体可以有多个问题。这就是我如何看待关系注释:

Teacher.java

@OneToMany(mappedBy = "teacher", cascade = CascadeType.ALL)
private List<Survey> surveys = new ArrayList<Survey>();

Survey.java

@ManyToOne
@JoinColumn(name = "teacherid", referencedColumnName = "id")
private Teacher teacher;

@OneToMany(mappedBy = "survey", cascade = CascadeType.ALL)
private List<Question> questions = new ArrayList<Question>();

Question.java

@ManyToOne
@JoinColumn(name = "surveyid", referencedColumnName = "id")
private Survey survey;

在每个课程中,我都有一个addSometing()方法,如下所示: survey.addQuestion(q)

public void addQuestion(Question q) {
    if (q != null) {
        q.setSurvey(this);
        questions.add(q);
    }
}

然后,最后,我的DAO中的每个实体的另一个addSomething() - 方法如下所示:

public void addSurvey(Survey survey) {

    EntityManager em = emf.createEntityManager();
    EntityTransaction tx = em.getTransaction();

    try {
        tx.begin();
        em.persist(survey);
        tx.commit();

    } catch (Exception e) {

        e.printStackTrace();

        if (tx.isActive()) {
            tx.rollback();
        }

    } finally {
        em.close();
    }

}

当我运行我的代码时,我设法创建一个Teacher-object并将其添加到数据库中。然后我创建一个Question-object并将其添加到一个新的Survey-object并将其添加到我的教师,它也可以正常工作。但是当我尝试将问题和调查对象持久化到数据库并合并/更新Teacher-object时,我得到一个InvalidStateException:

Encountered unmanaged object "no.hib.dat104.obl3.model.Survey@52892ae7" in life cycle state  unmanaged while cascading persistence via field "no.hib.dat104.obl3.model.Question.survey" during flush.  However, this field does not allow cascade persist. You cannot flush unmanaged objects or graphs that have persistent associations to unmanaged objects.

我不认为我正在做这些事情的方式是使用JPA实体的正确方法。谁能给我一个简短的解释,说明我应该如何做到这一点或指出我正确的方向?我知道Entity Object Life Cycle,但我不确定如何在我的项目中解决这个问题。

1 个答案:

答案 0 :(得分:0)

您在addSurvey方法中获取的EntityManager上下文是新的,因此为空。据推测,当您坚持调查时,它会有问题,并会分配一名教师。在您的模型中,教师实例是数据库中的现有对象,并且从Survey到Teacher的引用没有级联选项 - 当JPA遇到模型中的非托管对象时,需要抛出异常,因为它没有。知道你打算用它做什么。

在您的模型中有很多方法可以解决这个问题,但它们依赖于许多其他外部因素。我能想到的最快的解决方案是稍微改变一下,以便教师ManyToOne引用使用cascade = CascadeType.Merge选项,然后在addSurvey方法中使用em.merge(survey);。然后,JPA将确定调查和问题是新的并插入它们,同时它将现有教师实例中的任何更改合并到数据库中。

还有许多其他选项,例如使用扩展的持久性单元,可用于读取Teacher实例以及保留Survey和Question实例。什么是最适合您的应用取决于您在不同情况下预期会发生什么。

相关问题