2 Replies Latest reply on Feb 6, 2009 2:13 PM by adamw

    Problems with @VersionsJoinTable

    msilva

      I'm trying to use the @VersionsJoinTable annotation in a @OneToMany relationship but it doesn't seem to generate the right table structure (the join table isn't created at all).

      My test Entities:

      @Entity
      @Versioned
      public class Entity1{
      
       @Id
       private Long id;;
      
       private String prop;
      
       @OneToMany
       @VersionsJoinTable(name= "joinTable")
       private List<Entity2> entities2;
      ....
      }



      @Entity
      @Versioned
      public class Entity2 {
      
       @Id
       private Long id;
      
       private String prop;
      ....
      }


      If I use the JPA annotation (@JoinTable) instead, the tables are created correctly, but I encounter problems when fetching the related collection with the VersionsReader.

      Am I misusing the annotation?

      Thanks,
      Marcus


        • 1. Re: Problems with @VersionsJoinTable
          msilva

          I made some additional tests, now using the hibernate-envers module (version 3.4.0-SNAPSHOT). What I'd really like to do is add extra columns to the join table, so I decided to create an explicit join entity:

          @Audited
          @Entity(name = "MIDDLE")
          public class Middle {
           @Id
           @GeneratedValue
           private Long id;
          
           @Column(name = "ID_ENT1")
           private Long idEnt1;
          
           @Column(name = "ID_ENT2")
           private Long idEnt2;
          
           private String prop; // Extra column
          
           // Getters and setters
          }
          


          Therefore, Entity1 became:

          @Entity
          @Audited
          public class Entity1 {
           @Id
           @GeneratedValue
           private Long id;
          
           @OneToMany
           @JoinTable(name = "MIDDLE", joinColumns = @JoinColumn(name = "ID_ENT1"), inverseJoinColumns = @JoinColumn(name = "ID_ENT2"))
           private List<Entity2> entities2;
          
           private String prop;
          
           // Getters and setters
          }
          


          Notice I'm using the regular @JoinTable annotation. My test case is the following:

          @Test
          public void test() {
           Entity1 ent1 = new Entity1();
           Entity2 ent2a = new Entity2();
           Entity2 ent2b = new Entity2();
          
           ent1.setProp("prop1");
           ent2a.setProp("prop2a");
           ent2b.setProp("prop2b");
          
           List<Entity2> list = new ArrayList<Entity2>();
           list.add(ent2a);
           list.add(ent2b);
           ent1.setEntities2(list);
          
           em.getTransaction().begin(); // Using EntityManager
           em.persist(ent2a);
           em.persist(ent2b);
           em.persist(ent1);
           em.getTransaction().commit();
          
           Entity1 ent1 = ar.find(Entity1.class, 1L, 1); // Using AuditReader
           System.out.println(ent1.getEntities2());
          }
          


          The last command prints an empty list, meaning it wasn't able to fetch the related collection. Looking at the database, I found out that Hibernate generates the tables MIDDLE and MIDDLE_AUD, but only the first one is used (MIDDLE_AUD remains empty all the time).

          I also tried to use the following annotation instead:

           @OneToMany
           @AuditJoinTable(name = "MIDDLE", inverseJoinColumns = @JoinColumn(name = "ID_ENT2"))
           private List<Entity2> entities2;
          


          This gives me the following exception:

          javax.persistence.PersistenceException: [PersistenceUnit: persistenceUnit] Unable to build EntityManagerFactory
           at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:677)
           at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:126)
           at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
           ...
          Caused by: org.hibernate.HibernateException: could not init listeners
           at org.hibernate.event.EventListeners.initializeListeners(EventListeners.java:205)
           at org.hibernate.cfg.Configuration.getInitializedEventListeners(Configuration.java:1338)
           at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1327)
           ...
          Caused by: org.hibernate.DuplicateMappingException: duplicate import: MIDDLE refers to both MIDDLE and br.com.touchtec.versionPoc.Middle (try using auto-import="false")
          


          Using both annotations together brings up the same stack trace. Apparently, Envers is trying to generate a MIDDLE table because I declared it on the @AuditJoinTable annotation, but it gives up when it finds that the entity MIDDLE already exists (since I declared it on persistence.xml). However, I wanted Envers to use my entity as join table.

          Is it possible to do what I want? Am I missing something?

          Thanks again,
          Marcus

          • 2. Re: Problems with @VersionsJoinTable
            adamw

            Hello,

            your first mapping looks fine. There is a test in Envers that is almost identical - and it passes. Can you maybe post a full example? Along with your configuration etc.

            As for the second example, I think the mapping is wrong. Either you declare the middle entity as a "JPA entity", and then the relation from Entity1 must go to Middle (so Entity1 must have a list of Middle). Or you just do a uni-directional relation to Entity2.

            Adam