4 Replies Latest reply on May 12, 2011 3:47 AM by Adam Warski

    ValidityAuditStrategy and non-generated PK

    Nikita D Newbie

      I have an entity for storing String key-value pairs (the equivalent of a properties file). The String key is the primary key (there is no generated id). I'd like to use ValidityAuditStrategy for auditing changes to this entity. The problem is when a row is deleted and later another row is inserted with the same key as the deleted one.

       

      When a row is deleted, a revision of type DEL is added, with the REVEND column set to null. When a row is added with the same PK, a revision of type ADD is added, with the REVEND column set to null. A subsequent call to update the row fails, because ValidityAuditStrategy expects to find exactly one row with a null REVEND value, but at this point there are 2 rows.

       

      It seems like the ADD revision should have updated the REVEND column of the DEL revision. Does that make sense?

       

      Thank you,

      Nikita

        • 1. ValidityAuditStrategy and non-generated PK
          Adam Warski Master

          Yes, I think in that scenario that should happen. Or the DEL can set rev = revend = revision at which the del happened.

          Usually IDs are unique so it's not a problem

           

          Adam

          • 2. ValidityAuditStrategy and non-generated PK
            Nikita D Newbie

            Thank you for the reply! I created an enhancement ticket for this in JIRA: http://opensource.atlassian.com/projects/hibernate/browse/HHH-6209

             

            Nikita

            • 3. ValidityAuditStrategy and non-generated PK
              Srinivas Nandina Newbie

              I am also running into a similar issue when reordering elements in an indexed collection using ValidityAuditStrategy.

               

              It is reproducible with the following code which uses the class 'org.hibernate.envers.test.entities.collection.StringListEntity'.

               

                      StringListEntity entity1 = new StringListEntity();

                      em.getTransaction().begin();

                      List<String> list1 = new ArrayList<String>();

                      list1.add("a");

                      list1.add("b");

                      list1.add("c");

                      entity1.setStrings(list1);

                      em.persist(entity1);

                      em.getTransaction().commit();

               

                      Integer id = entity1.getId();

                     

                      em.getTransaction().begin();

                      StringListEntity entity2 = em.find(StringListEntity.class, id);

                      List<String> list2 = new ArrayList<String>();

                      list2.add("c");

                      list2.add("a");

                      list2.add("b");

                      entity2.setStrings(list2);

                      em.getTransaction().commit();

                     

               

                      em.getTransaction().begin();

                      StringListEntity entity3 = em.find(StringListEntity.class, id);

                      List<String> list3 = new ArrayList<String>();

                      list3.add("a");

                      list3.add("c");

                      list3.add("b");

                      entity3.setStrings(list3);

                      em.getTransaction().commit();

                     

               

                      em.getTransaction().begin();

                      StringListEntity entity4 = em.find(StringListEntity.class, id);

                      List<String> list4 = new ArrayList<String>();

                      list4.add("b");

                      list4.add("a");

                      list4.add("c");

                      entity4.setStrings(list4);

                      em.getTransaction().commit();

               

              This reorders the indexed list like below:

              a, b, c --> c, a, b --> a, c, b --> b, a, c

               

              Caused by: java.lang.RuntimeException: Cannot find previous revision for entity StringListEntity_strings_AUD and id {REV=DefaultRevisionEntity(id = 4, revisionDate = May 10, 2011 5:49:17 PM), element=a, StringListEntity_id=1, mapkey=0}

                  at org.hibernate.envers.strategy.ValidityAuditStrategy.updateLastRevision(ValidityAuditStrategy.java:175)

                  at org.hibernate.envers.strategy.ValidityAuditStrategy.performCollectionChange(ValidityAuditStrategy.java:96)

                  at org.hibernate.envers.synchronization.work.PersistentCollectionChangeWorkUnit.perform(PersistentCollectionChangeWorkUnit.java:88)

                  at org.hibernate.envers.synchronization.AuditProcess.executeInSession(AuditProcess.java:114)

                  at org.hibernate.envers.synchronization.AuditProcess.doBeforeTransactionCompletion(AuditProcess.java:152)

                  at org.hibernate.engine.ActionQueue$BeforeTransactionCompletionProcessQueue.beforeTransactionCompletion(ActionQueue.java:543)

                  ... 7 more

               

              Is there any workaround available with ValidityAuditStrategy to accompolish the above?

               

              Thanks,

              Srinivas Nandina

              • 4. ValidityAuditStrategy and non-generated PK
                Adam Warski Master

                Ah, that's certainly a bug. Needs to be fixed

                 

                Adam