[hibernate-issues] [Hibernate-JIRA] Created: (HHH-5833) Insertion failure of a second entity in 1-N relationship when using PROPERTY access instead of FIELD access

Cyrille Charron (JIRA) noreply at atlassian.com
Tue Jan 11 07:36:05 EST 2011


Insertion failure of a second entity in 1-N relationship when using PROPERTY access instead of FIELD access
-----------------------------------------------------------------------------------------------------------

                 Key: HHH-5833
                 URL: http://opensource.atlassian.com/projects/hibernate/browse/HHH-5833
             Project: Hibernate Core
          Issue Type: Bug
          Components: core
    Affects Versions: 3.6.1
         Environment: Windows XP, JUnit test under Eclipse with HSQLDB.
            Reporter: Cyrille Charron
         Attachments: FamilyModel.zip, Hibernate-bug.txt, HibernateTest.zip

While testing JBossCache, i have stumbled onto an apparent bug of Hibernate, 
which throws a LazyInitializationException
on a 1-N bi-directional relation between an entity Address 
and two entities Person.

NB: there's no bug when using OpenJPA.

I have copied an extract of my java code 
and the stack trace with a breakpoint on the exception 
at line 366 into AbstractPersistentCollection.java 
at the end of this issue report.

If i am right, the bug arises because Hibernate tries to initialize 
a collection which is already in the state of initialization.

This bug appears when i link 2 Person entities to the same Address entity
via 1-N bi-directional relation, and if the Person's setter updates 
the 2 sides of this relation-ship by calling itself the Address's setter 
(this "helper" code in entities was to be sure
that the relation is updated on both sides, whoever is the owner).

In my example, this collection is the "inhabitants" attribute 
of my entity Address, in which i try to add a second entity Person,
which has an attribute "address" pointing on the entity Address.

Here is the "helper" code of the Person's setter :
{code}
    public boolean setAddress(Address address) {
        boolean done = false;
        if (this.address != address) {
            if (this.address != null) this.address.remInhabitant(this);
            this.address = address;
            if (this.address != null) this.address.addInhabitant(this);
            done = true;
        }
        return done;
    }
{code}

My Stateless Session Bean had only to update one side of the relation :
{code}
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void setAddressForPerson(int personId, int addressId) {
        Address address = findAddress(addressId);
        Person person = findPerson(personId);
        ...
        person.setAddress(address);
    }
{code}


In the stack trace we see that :
  we call Person.setAddress(Address) on my SECOND entity Person
  which calls PersistentSet.size() on Address's collection
  which calls PersistentSet(AbstractPersistentCollection).initialize(boolean)
  which calls TwoPhaseLoad.initializeEntity
  which calls PojoEntityTuplizer.setPropertyValues
  which calls Person.setAddress(Address) on my FIRST entity Person
  which calls PersistentSet.size() on Address's collection
  which calls PersistentSet(AbstractPersistentCollection).initialize(boolean)
  which throws the LazyInitializationException
as if the relation between my FIRST entity Person and entity Address 
has not finished its initialization.

This bug DISAPPEARS if i delete the "helper" code from my entity Person :
{code}
    public boolean setAddress(Address address) {
        this.address = address;
        return true;
    }
{code}
and if i update manually the both sides of the relation in my Session Bean :
{code}
    @TransactionAttribute(TransactionAttributeType.REQUIRED)
    public void setAddressForPerson(int personId, int addressId) {
        Address address = findAddress(addressId);
        Person person = findPerson(personId);
        ...
        if (person.getAddress() != null) person.getAddress().remInhabitant(person);
        if (address != null) address.addInhabitant(person);
        person.setAddress(address);
    }
{code}

I join 3 files :
  the model project (entities Person, Address and Family)
  the test project (Bean and JUnit)
  a resume of source code and the stack trace with some variables values.

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators: http://opensource.atlassian.com/projects/hibernate/secure/Administrators.jspa
-
For more information on JIRA, see: http://www.atlassian.com/software/jira

        


More information about the hibernate-issues mailing list