8 Replies Latest reply on Sep 29, 2010 6:58 AM by jonas.esser

    Problem with @ManyToMany relation

      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

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

          Add the following code in configuration:










          • 2. Re: Problem with @ManyToMany relation









            • 3. Re: Problem with @ManyToMany relation

              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.b

                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
                  adamw

                  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.b

                    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

                      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

                        Hi Daniel,

                         

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

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

                        Best Regards,

                        Jonas