JPA: mapping circular references

Hi all,

I'm trying to map a simple parent-to-children-knows-parent scenario, which contains circular references, using JPA annotations. Here is the current code:

@Entity

publicclass Assortmentimplements Identifiable{

@Id

@GeneratedValue

privatelong 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;

...

}

The DDL for the table is the following:

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));

When creating a basic tree (one root to which two children were added) and persisting this object using a simple entityManager.persist(root) call, I get the following (shortened) exception:

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)

...

Caused by: org.hibernate.exception.ConstraintViolationException: could not insert: [core.model.goods.Assortment]

at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:71)

...

Caused by: java.sql.SQLException: Attempt to insertnull 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)

...

It looks like the Hibernate EntityManager (the JPA implementation) is trying to insert anull 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 a lot,

GB

[3068 byte] By [gbilodeaua] at [2007-10-3 4:51:53]
# 1

Two things:

First, the Assortment.parent attribute needed to be annotated with @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:

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,

GB

gbilodeaua at 2007-7-14 22:56:38 > top of Java-index,Enterprise & Remote Computing,Enterprise Technologies...