Hi all,
I'm trying to persist a simple tree-like scenario but get an exception when Hibernate tries to insert NULL as the object's primary key. I have looked through the FAQ and forums, googled for everything and can't seem to figure it out. Can anybody point me in the right direction?
Hibernate version: Core 3.2.0.cr2, EntityManager 3.2.0.cr1 and Annotations 3.2.0.cr1
Mapping documents:
Code:
@Entity
public class Assortment implements Identifiable {
@Id
@GeneratedValue
private long id;
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent")
private Set<Assortment> subAssortments = new HashSet<Assortment>();
@ManyToOne(fetch = FetchType.LAZY)
private Assortment parent = null;
...
}
Code between sessionFactory.openSession() and session.close():Code:
public class AssortmentJpaDAO extends JpaDaoSupport implements AssortmentDAO {
public void saveAssortment(Assortment asmt) {
getJpaTemplate().persist(asmt);
}
}
Full stack trace of any exception that occurs:Code:
org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.exception.ConstraintViolationException: could not insert: [core.model.goods.Assortment]; nested exception is javax.persistence.EntityExistsException: org.hibernate.exception.ConstraintViolationException: could not insert: [core.model.goods.Assortment]
Caused by: javax.persistence.EntityExistsException: org.hibernate.exception.ConstraintViolationException: could not insert: [core.model.goods.Assortment]
at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.java:555)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:192)
at org.springframework.orm.jpa.JpaTemplate$5.doInJpa(JpaTemplate.java:264)
at org.springframework.orm.jpa.JpaTemplate.execute(JpaTemplate.java:192)
at org.springframework.orm.jpa.JpaTemplate.persist(JpaTemplate.java:262)
at core.dao.goods.AssortmentJpaDAO.saveAssortment(AssortmentJpaDAO.java:20)
at core.dao.goods.AssortmentJpaDAOTest.testSaveAssortmentOk(AssortmentJpaDAOTest.java:29)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:585)
at junit.framework.TestCase.runTest(TestCase.java:154)
at junit.framework.TestCase.runBare(TestCase.java:127)
at org.springframework.test.ConditionalTestCase.runBare(ConditionalTestCase.java:69)
at junit.framework.TestResult$1.protect(TestResult.java:106)
at junit.framework.TestResult.runProtected(TestResult.java:124)
at junit.framework.TestResult.run(TestResult.java:109)
at junit.framework.TestCase.run(TestCase.java:118)
at junit.framework.TestSuite.runTest(TestSuite.java:208)
at junit.framework.TestSuite.run(TestSuite.java:203)
at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:128)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [core.model.goods.Assortment]
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:40)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2044)
at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2481)
at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:47)
at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:290)
at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:180)
at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:108)
at org.hibernate.event.def.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:131)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:87)
at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:38)
at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.java:620)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:594)
at org.hibernate.impl.SessionImpl.persist(SessionImpl.java:598)
at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:186)
... 24 more
Caused by: java.sql.SQLException: Attempt to insert null into a non-nullable column: column: ID table: ASSORTMENT in statement [insert into Assortment (id, code, name, status, parent_id) values (null, ?, ?, ?, ?)]
at org.hsqldb.jdbc.Util.throwError(Unknown Source)
at org.hsqldb.jdbc.jdbcPreparedStatement.executeUpdate(Unknown Source)
at org.hibernate.id.insert.AbstractSelectingDelegate.performInsert(AbstractSelectingDelegate.java:33)
... 38 more
Name and version of the database you are using: HSQLDB 1.8.0.4 in-memory mode
The generated SQL (show_sql=true):Code:
Hibernate: insert into Assortment (id, code, name, status, parent_id) values (null, ?, ?, ?, ?)
Debug level Hibernate log excerpt:Don't know
DDL:Code:
CREATE TABLE ASSORTMENT (ID BIGINT PRIMARY KEY, CODE VARCHAR(5) NOT NULL, NAME VARCHAR(50) NOT NULL, STATUS TINYINT NOT NULL, PARENT_ID BIGINT, CONSTRAINT FK_ASMT_PARENT FOREIGN KEY (PARENT_ID) REFERENCES ASSORTMENT(ID));
It looks like the Hibernate EntityManager (the JPA implementation) is trying to insert a null value in the table's primary key (id). This understandable, since saving an object requires first knowing what the parent's ID is - although here the root has no parent and hence the parent's ID must be null.
How must I adapt my code to handle this particular scenario? Are my annotations correct? Should I change the data structure definition instead?
Thanks!