8 Replies Latest reply on Apr 17, 2010 3:36 AM by adamw

    OneToMany and AuditMappedBy

    ebarendt

      I have two entities, Product and ProductSetting and a OneToMany/ManyToOne bidirectional relationship set up.  I'm attempting to add Envers to the mix by adding the appropriate annotations.  The problem is that when I load the Product via Envers, it loads the ProductSettings from all revisions, not just the one related to the Product.  My annotations are:

       

       

      class Product {
         @OneToMany(mappedBy = "product", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
         @Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
         @Fetch(FetchMode.SUBSELECT)
         @Audited
         @AuditMappedBy(mappedBy = "product")
         public Set<ProductSetting> getProductSettings() {
            return productSettings;
         }
      }
      

       

      and

       

      class ProductSetting {
         @ManyToOne
         @JoinColumn(name = "productid",  nullable = false, insertable = false, updatable = false)
         @Audited
         public Product getProduct() {
            return product;
         }
      }
      

       

      I had it working with AuditJoinTable, but according to the docs and the forum, that should be unnecessary given this bidirectional relationship.  Any suggestions?

       

      Thanks,

      Eric

        • 1. Re: OneToMany and AuditMappedBy
          adamw

          Hmm the mappings looks a little weird - which side owns the relationship? Because product has a @OneToMany(mappedBy) and produce settings has insertable and updatable set to false. So are changes ever persisted?

           

          Anyhow, the fact that you get back all revisions is quite weird. Could you create a small reproducing test case and attach it to a JIRA issue? There are tests for your scenario and they work fine so I don't really know what might be happening.

           

          Adam

          • 2. Re: OneToMany and AuditMappedBy
            ebarendt

            Sorry, that was left-over from trying AuditJoinTable instead of this way.  Insertable/Updatable were originally not specified.

             

            FWIW, the AuditJoinTable worked correctly, but seems like a hack given that it is supposed to work with this way.  Also, I forgot to mention I'm using Hibernate 3.3 with Envers 1.2.2.  We're on JBoss 4.2.3, which doesn't appear to work with Hibernate 3.5 - so no upgrading yet.

             

            Here are our audit tables, in case there's something weird here:

             

            CREATE TABLE `product_AUD` (
              `REV` int(11) NOT NULL,
              `REVTYPE` int(11) NOT NULL,
              `PRODUCTID` bigint(20) NOT NULL,
              `NAME` varchar(256) default NULL,
              CONSTRAINT pk_product_aud PRIMARY KEY  (`PRODUCTID`, `REV`)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
            
            CREATE TABLE `productsetting_AUD` (
              `REV` int(11) NOT NULL,
              `REVTYPE` int(11) NOT NULL,
              `ID` bigint(20) NOT NULL,
              `PRODUCTID` bigint(20),
              `SETTINGNAME` varchar(256),
              `VALUE` varchar(256)
            ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE utf8_bin;
            

             

            If you don't have any other ideas, I can try to make a test case.

             

            Thanks,

            Eric

            • 3. Re: OneToMany and AuditMappedBy
              ebarendt

              Sorry, I was mistaken - the AuditJoinTable didn't work either.

              • 4. Re: OneToMany and AuditMappedBy
                adamw

                Hello,

                 

                in case of a normal relation mapping, using @ManyToOne + @OneToMany(mappedBy = ""), you don't need the @AuditMappedBy or any other envers annotations. @Audited should work just fine.

                 

                The tables look ok, if there was anything wrong with them you would get an exception.

                 

                So a test case would be great .

                 

                Btw. the thing that isn't working is that you're getting all the revisions when reading the relation from an entity that's obtained using AuditReader?

                 

                Adam

                • 5. Re: OneToMany and AuditMappedBy
                  ebarendt

                  I spent most of yesterday trying to get it to work and ended up just merging the two tables together (instead of key/value pairs in the ProductSetting table, they're columns in the Product table).  I'd still like to see it resolved, but I can't spend more time getting our app to work.

                   

                  Our query:

                   

                  AuditReader auditReader = AuditReaderFactory.get(entityManager);
                  AuditQuery query = auditReader.createQuery()
                        .forRevisionsOfEntity(Product.class, false, true)
                        .add(AuditEntity.revisionNumber().gt(revision))
                        .addOrder(AuditEntity.revisionNumber().desc());
                  

                   

                  (revision is a user-supplied argument)

                   

                  The goal is to find all revisions of a given entity since a given revision.

                   

                  Thanks,

                  Eric

                  • 6. Re: OneToMany and AuditMappedBy
                    adamw

                    Hmm ... but what exactly doesn't work? That is, what operations returns what results, and what are the expected results?

                     

                    Adam

                    • 7. Re: OneToMany and AuditMappedBy
                      ebarendt

                      So let's say that query returned one Product.  I would expect that if I call "product.getProductSettings()", it would return the ProductSettings only for the revision the Product is in.  Instead, I get the ProductSettings for *all* revisions.

                      • 8. Re: OneToMany and AuditMappedBy
                        adamw

                        Ah ok. And if you retrieve the same product using AuditReader.find?

                        Anyway, this should work, and is covered in fact by a lot of tests, so I would be really curious to see a reproducing test for this to find out what's happening

                         

                        Adam