我在JPA项目中有2个实体:
类别和问题。所以每个类别都会有一个问题列表,每个问题都将成为一个类别的一部分(OnetoMany关系)。我通过两个实体中的set / add方法管理双向关系:
问题:
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "Qcategory")
private Category category;
public void setCategory(Category category) {
this.category = category;
if (category != null && !category.getQuestions().contains(this)) {
category.addQuestion(this);
}
}
类别:
@OneToMany(cascade = { CascadeType.ALL }, mappedBy = "category")
private List<Question> questions= new ArrayList<Question>();
public void addQuestion(Question question) {
this.questions.add(question);
if (question.getCategory() != this) {
question.setCategory(this);
}
}
我首先创建一个类别。
Category category1 = new Category();
category1.setName = "exampleCategory";
我通过我的存储库将其添加到数据库中(以类似于addOrUpdate的方式添加,如下所示)
之后我创建了一个问题
Question question1 = new Question();
我将问题的类别设置为category1
question.setCategory = category1;
在此之后,我还尝试通过调用下面的addOrUpdate方法将问题持久化到db。然后我收到一个错误:
....:javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: jpa.entities.Category
我使用的存储库方法如下:
@Override
public boolean addOrUpdate(Question question) {
EntityManagerFactory emf = JPARepositoryFactory
.getEntityManagerFactory();
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
Question tempQuestion = null;
try {
if (question.getId() != null) {
tempQuestion = em.find(Question.class,
question.getId());
}
if (tempQuestion == null) {
em.persist(question);
} else {
tempQuestion .setCategory(question.getCategory());
... (other setters)
tempQuestion = em.merge(question);
}
} catch (Exception e) {
....logging... }
tx.commit();
em.close();
emf.close();
return true;
}
任何建议都会受到欢迎。
答案 0 :(得分:1)
因此,您只能在实体上调用一次persist。该错误意味着您已经在传入的Question对象上调用了persist,但是您在另一个事务中执行了此操作。如果要将Question对象重新附加到持久性上下文,则需要调用merge或从数据库重新加载它。
答案 1 :(得分:0)
在持久或合并之前,您需要做的是在每个问题中设置类别引用。
答案 2 :(得分:0)
[注意:这可能不是直接答案,只是几点观察]
使用每个方法调用初始化EntityManagerFactory
绝对不是一个好习惯。相反,应该在应用程序启动期间创建一次。
您正在传递Category
,这是另一个持久性上下文的一部分,而addOrUpdate
处于托管状态。
您对自己的关系有cascade=MERGE
/ cascade=PERSIST
或cascade=ALL
。
也许,你可以在当前的thransaction&amp;中再次通过id获取Category
。在坚持之前将其设置在question
。
来自文档:
双向关系必须遵循这些规则。
- 双向关系的反面必须通过使用@OneToOne的mappedBy元素引用其拥有方, @OneToMany或@ManyToMany注释。 mappedBy元素指定 作为所有者的实体中的财产或字段 关系。
- 多对一双向关系的许多方面不得定义mappedBy元素。许多方面始终是拥有方 关系。
- 对于一对一的双向关系,拥有方对应于包含相应外键的一侧。
- 对于多对多双向关系,任何一方都可能是拥有方。