Uploaded image for project: 'Hibernate ORM'
  1. HHH-8093

Add the ability to handle related entity not found gracefully

    Details

    • Type: New Feature
    • Status: Closed
    • Priority: Major
    • Resolution: Out of Date
    • Affects versions: 4.2.0.Final
    • Fix versions: None
    • Components: hibernate-envers
    • Environment:
      Hibernate 4.2.0.Final, Oracle 11g or SQL Server 2008, Jboss 7.1.1
    • Last commented by a user?:
      true
    • Sprint:

      Description

      currently when querying audit data, if the related entity is not found, Envers will throw such exception:

      Employee.java
      @Audited
      class Employee {
        private Integer id;
        private Company company; //many to one relation
        private String firstName;
        private String lastName;
      }
       
      @Audited
      class Company {
        private Integer id;
        private String name;
      }
      

      Unable to find test.Company with id 10: javax.persistence.EntityNotFoundException: Unable to find test.Company with id 10
      at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:155)
      at org.hibernate.proxy.AbstractLazyInitializer.checkTargetState(AbstractLazyInitializer.java:235)
      at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:171)
      at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:259)
      at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
      at test.Company.hashCode(Company.java: 234)
      at org.apache.commons.lang3.builder.HashCodeBuilder.append(HashCodeBuilder.java:850)
      at test.Employee.hashCode(Company.java:222)
      at org.hibernate.envers.tools.Triple.hashCode(Triple.java:74)
      at java.util.HashMap.put(HashMap.java:372)
      at org.hibernate.envers.reader.FirstLevelCache.putOnEntityNameCache(FirstLevelCache.java:87)
      at org.hibernate.envers.entities.EntityInstantiator.createInstanceFromVersionsEntity(EntityInstantiator.java:104)
      at org.hibernate.envers.query.impl.RevisionsOfEntityQuery.list(RevisionsOfEntityQuery.java:134)
      at org.hibernate.envers.query.impl.AbstractAuditQuery.getResultList(AbstractAuditQuery.java:105)

      It will be better to give an option to not throw exception in this case, because this can happen in real world. For example, at first, only Employee is audited, and the company field in Employee is annotated as targetAuditMode=RelationTargetAuditMode.NOT_AUDITED. After the system has been running for several months, Company becomes audited as well. Then problem happens. When viewing Employee history, the above exception keeps happening, even if all current company entities have been put into audit table.

      The reason is when loading a revision of Employee and the related Company, Envers always tries to load Company with the max revision number equal or less than Employee's revision number. One possible workaround is to initialize Company audit table by populating all companies with revision number 0. However, what about if company has a relation with some other entities which has already been audited? Then it happens again. This is a real case in an existing project where not all domain objects are JPA entities.

      Apart from this scenario, the problem can easily happen when implementing a purging feature. For example, a task runs weekly to purge history records older that 6 months. As the object graph can be complicated, it's hard to make sure there's no orphan relation in audit tables.

      In fact, the problem can be solved by handling relation not found gracefully. For instance, the strategy to look up relation could be:
      1. Look up related entity with the max revision number equal or less than the targeted entity's revision number.
      2. If not found, look up related entity with the min revision number larger than the targeted entity's revision number.
      3. If not found, look up related entity in "current" version.
      4. If not found, return null or empty entity with id field populated.

      See the thread in forum:
      https://community.jboss.org/message/801783

        Attachments

          Issue links

            Activity

              People

              • Votes:
                13 Vote for this issue
                Watchers:
                9 Start watching this issue

                Dates

                • Created:
                  Updated:
                  Resolved: