1 Reply Latest reply on Aug 23, 2010 7:35 AM by code6226

    @AuditMappedBy Help

    code6226

      My project uses Hibernate Mappings (Hibernate 3.5.4). The two relevant abtract classes are AttributeValues and AttributesTypes. These are then joined-subclassed with the classes: TextAV / TextAT, NumberAV / NumberAT, EnumAV / EnumAT ... (respectively).

       

      My issue is only with the last (EnumAV), for it seems to fall into the special case that needs the @AuditMappedBy annotation, as described here: http://docs.jboss.org/envers/docs/index.html#exceptions-onetomanyjoincolumn

       

      AttributeValue HBM:

       

      <class name="AttributeValue" table="AV" lazy="false">
          <id name="id" column="ID" type="java.lang.Integer">
            <generator>
              <param name="segment_value">av</param>
            </generator>
          </id>
          
          ...
      
          <joined-subclass name="TextAV" table="AV_TEXT" lazy="false">
            <key column="ID_AV" />
            <property name="value" column="VALUE" length="4000" />
            <many-to-one name="attributeType" column="ID_AT" not-null="true" />
          </joined-subclass>
      
          <joined-subclass name="EnumAV" table="AV_ENUM" lazy="false">
            <key column="ID_AV" />
            <property name="name" column="NAME" length="255" not-null="true" />
            <property name="description" column="DESCRIPTION" length="4000" />
            <many-to-one name="attributeType" column="ID_AT" not-null="true" insert="false" update="false" />
          </joined-subclass>

       

      AttributeType HBM:

       

      <class name="AttributeType" table="AT" lazy="false">
          <id name="id" column="ID" type="java.lang.Integer">
            <generator>
              <param name="segment_value">av</param>
            </generator>
          </id>
          
          <property name="name" column="NAME" length="255" not-null="true" unique="true" />
          <property name="description" column="DESCRIPTION" length="4000" />
          <property name="mandatory" column="MANDATORY" length="1" not-null="true" />
          <property name="position" column="POS" insert="false" update="false" />
          
          ...
      
          <joined-subclass name="TextAT" table="AT_TEXT" lazy="false">
            <key column="ID_AT" />
            <property name="multiline" column="MULTILINE" length="1" not-null="true" />
            <set name="attributeValues" lazy="true" inverse="true" cascade="all">
              <key column="ID_AT" />
              <one-to-many />
            </set>
          </joined-subclass>
      
          <joined-subclass name="EnumAT" table="AT_ENUM" lazy="false">
            <key column="ID_AT" />
            <property name="multiassignmenttype" column="MULTIVALUE" length="1" not-null="true" />
            <list name="attributeValues" lazy="true" cascade="all">
              <key column="ID_AT" not-null="true" />
              <list-index column="POS" />
              <one-to-many />
            </list>
          </joined-subclass>

       

      The issue is that when I use Envers to retrieve an old EnumAV, I can only get its Name, not its EnumAT .

      Looking at the database tables (MySQL), the av_enum_aud table has all its ID_AT values null. The at_aud table also has the POS column with only null values.

      Another table was created, however, called enumat_enumav_aud, which has all its columns filled in: ID_AT, ID_AV, POS, REVTYPE. Envers must not be reading from this additional table.

       

      So I tried using @AuditMappedBy in various ways, but nothing seemed to change. Best example of how to use it that I could find was the ParentIndexedListJoinColumnBidirectionalRefIngEntity.java test case. Trying to use the same format myself, I came up with this:

       

      Class:EnumAV (No change)
      @Entity
      @Audited
      public class EnumAV extends AttributeValue {
      
        private String name;
       
        private String description;
      
        private EnumAT attributeType;
      
      ...
      

       

      Class:EnumAT 
      @Entity
      @Audited
      public class EnumAT extends AttributeType implements MultiassignementType {
      
        private boolean      multiassignmenttype;
      
        @AuditMappedBy(mappedBy = "attributeType", positionMappedBy = "position")
        private List<EnumAV> attributeValues = new ArrayList<EnumAV>();
      

       

      The "position" Integer is defined in the AttributeType abstract class.

       

      This didn't seem to have any effect... What should I do?

        • 1. Re: @AuditMappedBy Help
          code6226

          I've created a test project, where I tried to replicate the part that causes my issue. There are only two classes, and they are not subclassed: SprocketAT and SprocketAV

           

          The Hibernate Mapping XML:

           

          <class name="SprocketAV" lazy="false">
              <id name="id" column="ID_AV">
                <generator />
              </id>
              <property name="name" column="NAME" length="255" not-null="true" />
              <property name="description" column="DESCRIPTION" length="4000" />
           
              <property name="position" column="POSX" insert="false" update="false" /> 
              <many-to-one name="attributeType" column="ID_AT" not-null="true" insert="false" update="false" />
             </class>
             
             <class name="SprocketAT" lazy="false">    
              <id name="id" column="ID_AT">
                <generator />
              </id>    
              <property name="name" column="NAME" length="255" not-null="true" unique="true" />
              <property name="description" column="DESCRIPTION" length="4000" />
              
                <list name="attributeValues" lazy="true" cascade="all">
                  <key column="ID_AT" not-null="true" />
                  <list-index column="POSX" />
                  <one-to-many />
                </list>
          
             </class>
          

           

          Class: SprocketAV

           

          @Entity
          @Audited
          public class SprocketAV implements Serializable {
            private static final long serialVersionUID = 3828832892231451926L;
          
            private Integer id;
            private String  name;
            private String  description;
             private Integer    position;
          
            private SprocketAT attributeType;
          
               ... [ Getters / Setters ]

           

          Class: SprocketAT

           

          @Entity
          @Audited
          public class SprocketAT implements Serializable {
            private static final long serialVersionUID = 1762832892231451926L; 
          
            private Integer id;
          
            private String           name;
          
            private String           description;
          
            @AuditMappedBy(mappedBy = "attributeType", positionMappedBy = "position")
            private List<SprocketAV> attributeValues = new ArrayList<SprocketAV>();
          
               ... [ Getters / Setters ]
          
          

           

          I generate the tables using Ant, via org.hibernate.tool.ant.EnversHibernateToolTask, and persist some test objects: 1 parent AT, with 2 children AVs. This is Revision1.

          Then, I rename all 3 objects by adding "a" to the end of their name. This is Revision2.

           

          Issue1: Whether or not I include the @AuditMappedBy annotation seems to make no difference on the table structure. Either way, an extra sprocketat_sprocketav_aud table is always generated.

          Issue2: Also, this table only has entries for Revision1, not 2. Is this correct? EDIT: That seems ok, as there only seem to be entries made in this table when the relationship between the objects changes.

           

          Here's what the tables look like:

          sprocket_tables.PNG

          Anything I can do to make @AuditMappedBy have an effect?

           

          PS: Strangely, in this test project, I am able to retrieve the objects from revision 1 and 2 correctly. Still investigating why...