4 Replies Latest reply on Jul 2, 2006 3:34 AM by chrismalan

    Hibernate Exception When Deleting OneToMany EJB3 Entity

    michael.litherland

      Hi,

      I've created a OneToMany bidirectional relationship between two tables. The problem I'm having is a Hibernate exception when I go to delete the child object. According to the EJB3 book recently published by O'reilly it says to ensure the operation is performed from the ManyToOne side or the database operations won't happen. It's when I do this that I get the exception (optional = false on the ManyToOne so I have to use the EM and just do a remove).

      parent.getKids().remove(kid);
      em.remove(kid); // Throws exception
      


      throws

      Caused by: javax.persistence.PersistenceException: org.hibernate.NonUniqueObjectException: a different object
      with the same identifier value was already associated with the session: [com.ati.raa.entities.TdmUserMapping#4
      52]
       at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.jav
      a:567)
       at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:225)
       at org.jboss.ejb3.entity.TransactionScopedEntityManager.remove(TransactionScopedEntityManager.java:187
      )
       at com.ati.raa.bl.UserLogicBean.removeUserMapping(UserLogicBean.java:98)
       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 org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:112)
       at org.jboss.ejb3.interceptor.InvocationContextImpl.proceed(InvocationContextImpl.java:166)
       at org.jboss.ejb3.interceptor.EJB3InterceptorsInterceptor.invoke(EJB3InterceptorsInterceptor.java:63)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.entity.TransactionScopedEntityManagerInterceptor.invoke(TransactionScopedEntityManag
      erInterceptor.java:54)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.ejb3.AllowedOperationsInterceptor.invoke(AllowedOperationsInterceptor.java:47)
       at org.jboss.aop.joinpoint.MethodInvocation.invokeNext(MethodInvocation.java:101)
       at org.jboss.aspects.tx.TxPolicy.invokeInOurTx(TxPolicy.java:79)
       ... 49 more
      


      If it's relevant I'm using JBoss 4.0.4.GA on Java 1.5.0_06 (OS X) talking to PostgreSQL 8.1, and of course the EJB3 deployment profile for JBoss.

      I'm sure this is something I'm not sure about with the session, but I've been really beating myself up over this for about a week now and I need to resolve the issue. Any help would be much appreciated.

      Thanks,
      Mike

        • 1. Re: Hibernate Exception When Deleting OneToMany EJB3 Entity
          chrismalan

          Hi Mike,

          Sometimes you just have to think in database terms. Your kids table has a foreign key field for the primary key of the table called parent. There is nothing in the parent table to give any indication of how many kids the specific parent has.

          What this boils down to is this: just do a em.remove(kid) That will take care of the relationship to the parent. Don't do parent.getKids().remove(kid);

          Give it a go.

          • 2. Re: Hibernate Exception When Deleting OneToMany EJB3 Entity
            michael.litherland

            Chris, thanks so much for the reply.

            You're right, this got rid of the hibernate exception. However I'm still missing something. This is the code as it stands right now:

            KidBean kid = parent.getKids().get(mappingIndex);
            em.remove(kid);
            


            But when I go to reference the parent again the kid is still there. What's worse is that I noticed in the database a new entry has been created for the kid. (So it's not the same one, but a new one, if you want to be technical - one with almost all the same properties.) This is the DB table before the remove:

            sa=> select * from tdm_user_mapping;
             mapping_id | user_id | entity_type | entity_id
            ------------+---------+-------------+-----------
             450 | 100 | group | 50
             550 | 100 | group | 100
            


            and after, notice that one with mapping_id 550 is the one removed:

            sa=> select * from tdm_user_mapping;
             mapping_id | user_id | entity_type | entity_id
            ------------+---------+-------------+-----------
             450 | 100 | group | 50
             600 | 100 | group | 100
            


            Trying various combinations of em.refresh(parent), em.merge(parent) and em.find(Parent.class, parentId) result in either nothing happening or a new exception:

            Caused by: java.lang.RuntimeException:
            org.jboss.tm.JBossRollbackException: Unable to commit,
            tx=TransactionImpl:XidImpl[FormatId=257, GlobalId=michael-
            litherlands-computer.local/112, BranchQual=, localId=112]
            status=STATUS_NO_TRANSACTION; - nested throwable:
            (javax.persistence.EntityNotFoundException:
            org.hibernate.ObjectDeletedException: deleted entity passed to persist:
            [org.me.KidBean#<null>])
            


            So clearly I'm missing something else. I'm sure it's just that my heads not in the right place. Could I get another hint from anybody?

            Thanks much,
            Mike

            • 3. Re: Hibernate Exception When Deleting OneToMany EJB3 Entity
              michael.litherland

              OK, I guess I solved my problem. This is what I ended up doing:

              KidBean kid = parent.getKids().get(mappingIndex);
              em.remove(kid);
              parent.getKids().remove(mappingIndex);
              em.merge(parent);
              return parent;
              


              Seems if I don't return the parent changes aren't made evident in the front end and that detached bean ends up updating the database somehow. I didn't think that was possible. Anyway, by ensuring that the merge happens in the session bean and returning it to the front end things work.

              Thanks for everyone that looked and thanks again, Chris.

              • 4. Re: Hibernate Exception When Deleting OneToMany EJB3 Entity
                chrismalan

                Hi Michael,

                Sorry for coming back so late. The re-persisting of the kid when you try to delete it makes me think you have a cascade-type.all or, in any case, a cascade-type that includes persist.

                Make the cascade-type from parent to kid merge and remove only and from the kid to parent merge only (you should not really need it here) and see what happens. I had the same problem and this solved it.