JPA没有保留父子树

时间:2016-11-08 03:56:40

标签: java hibernate jpa

我有以下父母/子女关系,JPA注释:

@Entity
@Table(name = "project")
public class DefaultProject {
@OneToMany(mappedBy = "project", cascade = CascadeType.PERSIST)
private List<DefaultTask> tasks = new ArrayList(); ...
...
@Table(name = "task")
public class DefaultTask {
@ManyToOne(fetch=FetchType.LAZY, optional=false, cascade=CascadeType.PERSIST)
@JoinColumn(name = "PROJECT_ID", nullable = false)
private DefaultProject project; ...

然后,在JUnit测试用例中,我正在尝试以下内容:

EntityManager entityManager = entityManagerFactory.createEntityManager();
entityManager.getTransaction().begin(); 
DefaultProject testProject = getDummyProject();                       
testProject.setTasks(getDummyTasks());
entityManager.persist(testProject);
entityManager.getTransaction().commit();
entityManager.close();

单独保存实体是有效的,但在将它们保存在一起时会给出以下消息:

javax.persistence.PersistenceException: org.hibernate.PropertyValueException: not-null property references a null or transient value : org.demo.todo.entity.DefaultTask.project

对我而言似乎是先尝试保存孩子,但非持久的父ID导致异常。

保存这种关系的正确方法是什么?

谢谢!

编辑1 :在日志中启用TRACE级别后,我看到父实体(DefaultProject)获取了一个ID:

DEBUG org.hibernate.id.IdentifierGeneratorHelper: 78 - Natively generated identity: 26

然后在级联到孩子之后的几行,有些东西是空的:

TRACE org.hibernate.engine.internal.Cascade: 80 - Processing cascade ACTION_PERSIST_SKIPLAZY for: org.demo.todo.entity.DefaultProject
TRACE org.hibernate.engine.internal.Cascade: 419 - Cascade ACTION_PERSIST_SKIPLAZY for collection: org.demo.todo.entity.DefaultProject.tasks
TRACE org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1: 79 - Cascading persist to : org.demo.todo.entity.DefaultTask
TRACE org.hibernate.event.internal.AbstractSaveEventListener: 501 - Transient instance of: org.demo.todo.entity.DefaultTask
TRACE org.hibernate.event.internal.DefaultPersistEventListener: 183 - Saving transient instance
TRACE org.hibernate.event.internal.AbstractSaveEventListener: 157 - Saving [org.demo.todo.entity.DefaultTask#<null>]
TRACE org.hibernate.engine.internal.Cascade: 80 - Processing cascade ACTION_PERSIST_SKIPLAZY for: org.demo.todo.entity.DefaultTask
TRACE org.hibernate.engine.internal.Cascade: 130 - Done processing cascade ACTION_PERSIST_SKIPLAZY for: org.demo.todo.entity.DefaultTask
TRACE org.hibernate.engine.spi.ActionQueue: 298 - Adding an EntityIdentityInsertAction for [org.demo.todo.entity.DefaultTask] object
TRACE org.hibernate.engine.spi.ActionQueue: 248 - Executing inserts beforeQuery finding non-nullable transient entities for early insert: [EntityIdentityInsertAction[org.demo.todo.entity.DefaultTask#<null>]]
TRACE org.hibernate.engine.spi.ActionQueue: 253 - Adding insert with no non-nullable, transient entities: [EntityIdentityInsertAction[org.demo.todo.entity.DefaultTask#<null>]]

为什么它没有级联父实体ID? 谢谢!

1 个答案:

答案 0 :(得分:0)

尝试使用以下代码..

EntityManager entityManager = entityManagerFactory.createEntityManager();
EntityTransaction txn = entityManager.getTransaction(); 
txn.begin();
DefaultProject testProject = getDummyProject();                       
testProject.setTasks(getDummyTasks());
entityManager.persist(testProject);
txn.commit();
entityManager.close();