8 Replies Latest reply on Sep 29, 2010 6:58 AM by Jonas Esser

    Problem with @ManyToMany relation

    ke sun Newbie

      hello,
      Envers can work well in my project except the @ManyToMany relation. I have spent 2 days to find the problem but failed. Here is example of my code:

      @Audited
      @Entity
      @Table(name="user")
      public class User{
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       private Long id;
      
       @Column
       private String username;
      
       @ManyToMany(fetch = FetchType.EAGER)
       @JoinTable( joinColumns = { @JoinColumn(name = "user_id") }, inverseJoinColumns = @JoinColumn(name = "role_id"))
       @AuditJoinTable(inverseJoinColumns=@JoinColumn(name = "role_id"))
       private Set<Role> roles = new HashSet<Role>();
      
      //Here is the getters, setters, constructors, equals and hashCode.
      }


      @Audited
      @Entity
      @Table(name="role")
      public class Role{
       @Id
       @GeneratedValue(strategy = GenerationType.AUTO)
       private Long id;
      
       @Column
       private String name;
      
      //Here is the getters, setters, constructors, equals and hashCode.
      }



      There are 7 table in database:
      user,
      user_aud,
      role,
      role_aud,
      user_role,
      user_role_aud,
      revinfo.
      When I insert data to user, there is record in user, user_aud and user_role, but there is nothing in the table user_role_aud. Am I making some mistake in the code?
      Sorry for my pool English.


        • 1. Re: Problem with @ManyToMany relation
          ke sun Newbie

          I resolved this problem yet. I forget to add the envent of the collection.

          Add the following code in configuration:










          • 3. Re: Problem with @ManyToMany relation
            ke sun Newbie

            Sorry for the empty reply.
            The code is following:

            <event type="pre-collection-update">
             <listener class="org.hibernate.envers.event.AuditEventListener" />
             </event>
             <event type="post-collection-recreate">
             <listener class="org.hibernate.envers.event.AuditEventListener" />
             </event>
             <event type="pre-collection-remove">
             <listener class="org.hibernate.envers.event.AuditEventListener" />
             </event>



            • 4. Re: Problem with @ManyToMany relation
              Thibault Brachet Newbie

              Hi everybody, I post there because I'm facing a similar problem.

               

               

              I have no problem using Envers on @OneToOne and @OneToMany relations but I can't make it work with @ManyToMany  (using a JoinTable). Here's my models:

               

              @Entity
              @SequenceGenerator(name ="pacteGenerator", sequenceName = "SEQ_PACTE_PAC")
              @Table(name="T_PACTE_PAC"
              )
              @Audited
              @InformationModel( nomFonctionnel="Pacte" )
              public class PacteModel  implements java.io.Serializable {
              
                   private static final long serialVersionUID = 1L;
              
              
              
              
                  @Id
                    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "pacteGenerator")
              
                  @Column(name="PAC_ID", unique=true, nullable=false, precision=15, scale=0)
                    private Long id;
              
              
                  @ManyToMany(fetch=FetchType.LAZY)
                  @JoinTable(name="T_PACTE_MEMBR_PAM",joinColumns = {
                      @JoinColumn(name="PAC_ID", nullable=false, updatable=false,referencedColumnName="PAC_ID") }, inverseJoinColumns = {
                      @JoinColumn(name="POP_ID", nullable=false, updatable=false,referencedColumnName="POP_ID") })
                      private Set<PopulationModel> populationModels =  new LinkedHashSet<PopulationModel>(0);
              .
              .
              .
              }
              

               

              @Entity
              @SequenceGenerator(name = "populationGenerator", sequenceName = "SEQ_POPULATION_POP")
              @Table(name = "T_POPULATION_POP"
              /* ,schema="TESTADM" */
              )
              @Audited
              @InformationModel(nomFonctionnel = "Population")
              public  class PopulationModel implements java.io.Serializable, Cloneable {
              
                   private static final long serialVersionUID = 1L;
              
               @Id
                    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "populationGenerator")
              
                  @Column(name="POP_ID", unique=true, nullable=false, precision=15, scale=0)
                    private Long id;
              
              @Column(name = "POP_FIRST_NAME")
                   private String firstName;
              
                   @Column(name = "POP_LAST_NAME")
                   private String lastName;
              
              
              
              
              
              
              @ManyToMany( fetch = FetchType.LAZY, mappedBy = "populationModels")
               private Set<PacteModel> pacteModels = new LinkedHashSet<PacteModel>(0);
              
              
              
              .
              
              .
              
              .
              
              }
              
              

               

              I want to persist a new PacteModel with a new PopulationModel associated, here's my code:

               

              PacteModel pacte=new PacteModel();
              PopulationModel pop = new PopulationModel();
              pop.setFirstName("Verbal");
              pop.setLastName("KINT");
              
              pacte.getPopulationModels().add(ppm);
              
              getEntityManager().persist(entity); //This is a shortcut, I know I have no problems with my EntityManager 
              

               

              Here's the SQL requests and the Exception I got:

              Hibernate: 
                  insert 
                  into
                      T_POPULATION_POP
                      (POP_ID, POP_FIRST_NAME, POP_LAST_NAME) 
                  values
                      (?, ?, ?)
              Hibernate:
                   insert
                   into
                       T_PACTE_PAC           (PAC_ID)
                   values
                        (?)
              Hibernate: 
                  insert 
                  into
                      T_PACTE_MEMBR_PAM
                      (PAC_ID, POP_ID) 
                  values
                      (?, ?)
              Hibernate: 
                  select
                      SEQ_REV_ID_PAST.nextval 
                  from
                      dual
              16019 [http-8080-2] ERROR org.hibernate.transaction.JDBCTransaction - exception calling user Synchronization
              org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [PopulationModel_A#{id=5562500, REV=RevisionModel@1c4ee10}]
                   at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:191)
                   at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
                   at org.hibernate.ejb.event.EJB3SaveEventListener.saveWithGeneratedId(EJB3SaveEventListener.java:43)
                   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
                   at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
                   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
                   at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
                   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
                   at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:562)
                   at org.hibernate.impl.SessionImpl.save(SessionImpl.java:550)
                   at org.hibernate.envers.synchronization.work.CollectionChangeWorkUnit.perform(CollectionChangeWorkUnit.java:60)
                   at org.hibernate.envers.synchronization.AuditSync.executeInSession(AuditSync.java:125)
                   at org.hibernate.envers.synchronization.AuditSync.beforeCompletion(AuditSync.java:164)
                   at org.hibernate.transaction.JDBCTransaction.notifyLocalSynchsBeforeTransactionCompletion(JDBCTransaction.java:274)
                   at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:140)
                   at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
                   at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)
                   at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
                   at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
                   at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
                   at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
                   at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                   at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:635)
              

               

               

              *_A is the auditing table. We can see, the problem is only with persisting into the auditing table.

               

              Does Envers have some trouble with the collections of component as I can see there:

              http://www.jboss.org/files/envers/docs/index.html#exceptions-willbesupported

               

              The fact is when I put the @NotAudited on my

               @NotAudited
              private Set<PopulationModel> populationModels =  new LinkedHashSet<PopulationModel>(0);

               

              Here's what I get:

              Hibernate: 
                  insert 
                  into
                      T_POPULATION_POP
                      (POP_ID, POP_FIRST_NAME, POP_LAST_NAME) 
                  values
                      (?, ?, ?)
              Hibernate:
                   insert
                   into
                       T_PACTE_PAC           (PAC_ID)
                   values
                        (?)
              Hibernate: 
                  insert 
                  into
                      T_PACTE_MEMBR_PAM
                      (PAC_ID, POP_ID) 
                  values
                      (?, ?)
              Hibernate: 
                  select
                      SEQ_REV_ID_PAST.nextval 
                  from
                      dual
              Hibernate: 
                  insert 
                  into
                      REVINFO
                      (REV_ENTITIES_NAMES, REV_ID_TRANSACTION, REVTSTMP, REV) 
                  values
                      (?, ?, ?, ?)
              
              Hibernate: 
                  insert 
                  into
                      T_POPULATION_POP_A
                      (POP_ID, POP_FIRST_NAME, POP_LAST_NAME, REV, REVTYPE) 
                  values
                      (?, ?, ?, ?, ?)
              

               

               

              The problem disapear but there's no insertion in the auditing tables T_PACTE_PAC_A and T_PACTE_MEMBR_PAM_A.

               

               

              Here's my question, does somebody knows where I'm wrong or if Envers has problem with @ManyToMany and how to fix it?

               

               

              Thank's a lot and sorry for my poor english.

               

              Have a nice day.

              • 5. Re: Problem with @ManyToMany relation
                Adam Warski Master

                Hello,

                 

                first of all, collections of components still don't work, but that's not your case - as I can see you have a collection of entities.

                 

                Secondly, is there an id for the second entity, I can't see it in code?

                 

                This really should work without problems, there are tests exactly like it and they pass...

                 

                If it still doesn't work, could you create a small failing test and post it as a JIRA issue?

                 

                Adam    

                • 6. Re: Problem with @ManyToMany relation
                  Thibault Brachet Newbie

                  Hi Adam, Thank's for answering.

                   

                  Yes there's an id in both entities, I failed at copy/paste I guess (I'll add it in my precedent post).

                   

                  It still doesn't work, I'm gonna create a JIRA issue I think, I agree with you, I should have no problem.

                   

                   

                  Thank's

                   

                  If I find something, I'll post the solution here.

                  • 7. Re: Problem with @ManyToMany relation
                    djabornig Newbie

                    I have the same problem. I thought in the beginning its only a problem with ManyToMany and Sets but i still didn't find a workaround. I use envers 1.2.2. And somehow this error occurs only sporadically. I will try to figure out why this happens if the error occurs agains.

                     

                    The Mapping:

                     

                    @ManyToMany(fetch = FetchType.LAZY)
                    @JoinTable(name = "USER_ROLE")
                    private Set<Role> roles = new HashSet<Role>();

                     

                    org.hibernate.NonUniqueObjectException: a different object with the same identifier value was already associated with the session: [USER_ROLE_AUD#{REV=DefaultRevisionEntity(id = 24055, revisionDate = 30.03.2010 16:37:25), roles_id=1537, User_id=21939}]
                        at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:191)
                        at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:144)
                        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
                        at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
                        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
                        at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
                        at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
                        at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:562)
                        at org.hibernate.impl.SessionImpl.save(SessionImpl.java:550)
                        at org.hibernate.envers.synchronization.work.PersistentCollectionChangeWorkUnit.perform(PersistentCollectionChangeWorkUnit.java:87)
                        at org.hibernate.envers.synchronization.AuditSync.executeInSession(AuditSync.java:119)
                        at org.hibernate.envers.synchronization.AuditSync.beforeCompletion(AuditSync.java:158)
                        at org.hibernate.transaction.JDBCTransaction.notifyLocalSynchsBeforeTransactionCompletion(JDBCTransaction.java:274)
                        at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:140)
                        at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:655)
                        at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:732)
                        at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:701)
                        at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
                        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
                        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
                        at org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint.proceed(MethodInvocationProceedingJoinPoint.java:77)
                     
                    
                    • 8. Re: Problem with @ManyToMany relation
                      Jonas Esser Newbie

                      Hi Daniel,

                       

                      here is a jira ticket for the org.hibernate.NonUniqueObjectException:

                      http://opensource.atlassian.com/projects/hibernate/browse/HHH-3843

                      Best Regards,

                      Jonas