3 Replies Latest reply on Nov 4, 2010 10:09 AM by adamw

    Fetching revisions for an entity and its relations

    guillaume.t

      Hello,

       

      I am working on a projet using envers and am new to this framework. It works very well, but there is still one thing I can't help finding how to do.

       

      I have a Relative entity, which inherits from a Person entity. A Person may have several Relatives (through the entity PersonRelation) and has a reference to an Address.

      All there objects are Audited.

       

      I want to list all the revisions of a given Relative, which is itself a Person. I'm using the forRevisionsOfEntity function to achieve that, however there are two things I not getting to do.

      When an address is added to the Relative, a new Address revision (ADD) is generated, as well as a Person revision (MOD). Now I change the Address object, generating a new Address revision (MOD), but no Person revision, although the Relative object has been semantically changed (Address related to this Relative). Actually I just can receive from Envers the first revision of the Address. How can I use Envers to, while fetching the revisions of an Entity, fetching also the revisions of the referenced Entity to this Entity

      ?

       

      Some code below if needed.

       

       

      {code:java}
      @Entity
      @Audited
      @Inheritance( strategy = InheritanceType.SINGLE_TABLE )
      @DiscriminatorColumn( name = "PERSON_TYPE", discriminatorType = DiscriminatorType.INTEGER )
      @Table( name = "Person" )
      public class PersonImpl extends Person {

          @Id
          @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "PERSON_SEQ" )
          @SequenceGenerator( name = "PERSON_SEQ", sequenceName = "person_seq" )
          @Column( name = "PERSON_ID" )
          private Long person_id;

          // this column should not be used in business logic. It's only here to determine the type of the
          // concrete person object.
          @Column( name = "PERSON_TYPE", updatable = false, insertable = false )
          private Integer personType;

          private String name;
          private String givenname;

          @OneToOne( targetEntity = AddresseImpl.class, fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, optional = true )
          @JoinColumn( name = "PRIMARY_ADDRESS_ID_FK" )
          private Addresse primaryAddress; // audited
      }
      {code}

      {code:java}
      @Entity
      @Audited
      @DiscriminatorValue( "3" )
      public class RelativeImpl extends PersonImpl implements Relative {

          @OneToMany( mappedBy = "relative", targetEntity = PersonRelationImpl.class, fetch = FetchType.LAZY, cascade = { CascadeType.ALL } )
          @org.hibernate.annotations.Cascade( value = org.hibernate.annotations.CascadeType.ALL )
          private Set<PersonRelation> personRelations = new HashSet<PersonRelation>();


          @ManyToOne( targetEntity = ContactCategoryImpl.class, fetch = FetchType.LAZY, cascade = { CascadeType.ALL }, optional = true )
          @Audited( targetAuditMode = RelationTargetAuditMode.NOT_AUDITED )
          @JoinColumn( name = "CONTACT_CATEGORY_ID_FK" )
          private ContactCategory contactCategory;
      }
      {code}

      {code:java}
      @Entity
      @Audited
      @Table( name = "PERSON2RELATIVE" )
      public class PersonRelationImpl implements PersonRelation {

          @Id
          @GeneratedValue( strategy = GenerationType.SEQUENCE, generator = "PERSON2RELATIVE_SEQ" )
          @SequenceGenerator( name = "PERSON2RELATIVE_SEQ", sequenceName = "PERSON2RELATIVE_SEQ" )
          @Column( name = "PERSON2RELATIVE_ID" )
          private Long personRelationId;

          @ManyToOne( targetEntity = PersonImpl.class, fetch = FetchType.LAZY, cascade = { CascadeType.REFRESH } )
          @JoinColumn( name = "PERSON_ID_FK" )
          private Person person;

          @ManyToOne( targetEntity = RelativeImpl.class, fetch = FetchType.LAZY, cascade = { CascadeType.REFRESH } )
          @JoinColumn( name = "PERSON_RELATIVE_ID_FK" )
          private Relative relative;

          @OneToOne( targetEntity = NoteImpl.class, fetch = FetchType.EAGER, optional = true, cascade = CascadeType.ALL )
          @JoinColumn( name = "NOTE_ID_FK" )
          private Note note; // audited
      }
      {code}
        • 1. Re: Fetching revisions for an entity and its relations
          adamw

          This is a known limitation of Envers. If you modify an Address, no revision for the Person is generated (as Envers can't know which changes in the graph of objects accessible from a person are a semantic change, and which aren't; plus it would lead to a high number of revisions without changes). However, if you add or remove an address (an element of a collection), then a revision is generated (however that's configurable - see the manual). That's because a direct field on the person entity changed (the collection).

           

          Retrieving revisions of associated objects should be possible with the new ValidityAS, but is not yet implemented.


          Adam    

          • 2. Re: Fetching revisions for an entity and its relations
            guillaume.t

            Thanks Adam for your quick answer. At least I have the confirmation that it is not possible.
            What is this ValidityAS, a part of the implementation of Envers ?

             

            Guillaume

            • 3. Re: Fetching revisions for an entity and its relations
              adamw

              ValidityAuditStrategy - new in Hibernate 3.6.

               

              Adam