-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 
Author Message
 Post subject: JPA: mapping circular references
PostPosted: Wed Sep 13, 2006 6:51 am 
Newbie

Joined: Mon Aug 22, 2005 10:39 am
Posts: 7
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!


Top
 Profile  
 
 Post subject: Solved
PostPosted: Wed Sep 13, 2006 7:50 am 
Newbie

Joined: Mon Aug 22, 2005 10:39 am
Posts: 7
Two things:

First, the Assortment.parent attribute needed to be annotated with
Code:
@JoinColumn(name="parent_id")


Second, the SQL query sent by Hibernate used an HSQLDB specificity, the identity column, to generate the primary key. By setting hibernate.hbm2ddl.auto=true in my persistence.xml file and setting the log level to debug, I could see that the table was generated using this (approximate) statement:

Code:
CREATE TABLE ASSORTMENT (ID BIGINT GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, CODE VARCHAR(5), NAME VARCHAR(50), STATUS TINYINT NOT NULL, PARENT_ID BIGINT, CONSTRAINT FK_ASMT_PARENT FOREIGN KEY (PARENT_ID) REFERENCES ASSORTMENT(ID))


The "GENERATED BY DEFAULT AS IDENTITY" seems to be the key here.

Hope this helps someone out there.

Cheers!


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 2 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.