简体   繁体   中英

How to audit just part of superclass in hibernate?

I want to ask how to audit just a part of a superclass of entity, using hibernate annotations such as @AuditOverride , @Audited or else. Right now, I am using hibernate 5.2.12 version.
The annotations I can use only in a sublcass, because the superclass is in other module which shouldn't know anything about submodule.
Superclass contains one List<Items> and I don't want to it will be audited. Because when I am using one-to-many relationship I don't want that hibernate will create audit relationship table such as entity1_aud_entity2_aud . I just need entity1_aud and entity2_aud tables.
To refuse the audit relationship table I found two ways, but all of them is not fully correct:

1st. way

I duplicated the list variable and setters/getters to entity ( subclass ). And above list variable I write @NotAudited annotation. To make that annotation working I set access="field" attribute in hbm file. So hibernate not using setter and getter to access variable, so the value for the superclass isn't setting during data pulling .
Also I created list entity in which I write @AuditOverrides(value={@AuditOverride(forClass=Entity2.class), @AuditOverride(forClass=Item.class)}) . These annotations creates audit table for list entity. So full code for this auditing way is:
Entity1.class (main sublcass) [hibernate module]

@AuditOverrides(value = {
        @AuditOverride(forClass = Entity1.class),
        @AuditOverride(forClass = Superclass.class, name = "list", isAudited = false)
})
public class Entity1 extends Superclass {

    @NotAudited
    private List<Item> list = new ArrayList<>();

    @Override
    public List<Item> getList() {
        return super.getList();
    }

    @Override
    public void setList(List<Item> list) {
        super.setList(list);
    }
}  

Entity1.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="testing.Entity1" table="entity1">
        <id name="id" column="id">
            <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
                <param name="optimizer">none</param>
                <param name="increment_size">1</param>
                <param name="sequence_name">seq_entity_main</param>
            </generator>
        </id>

        <list name="list" cascade="all" lazy="false" access="field">
            <key>
                <column name="entity1_id" index="idx_fk_enm_entity_id"/>
            </key>
            <list-index>
                <column name="list_index"
                        not-null="true"
                        default="0"/>
            </list-index>
            <one-to-many class="testing.Entity2"/>
        </list>

        <property name="other" column="other" type="string" length="50"/>
    </class>
</hibernate-mapping>  

Superclass.class [domain module]

public class Superclass extends Builder {

    private List<Item> list = new ArrayList<>();
    private String other;

    public List<Item> getList() {
        return list;
    }

    public void setList(List<Item> list) {
        this.list = list;
    }

    public String getOther() {
        return other;
    }

    public void setOther(String other) {
        this.other = other;
    }
}  

Entity2.class (list item subclass) [hibernate module]

@AuditOverrides({
        @AuditOverride(forClass = Entity2.class),
        @AuditOverride(forClass = Item.class)})
public class Entity2 extends Item {
}  

Entity2.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="testing.Entity2" table="entity2">
        <id name="id" column="id">
            <generator class="org.hibernate.id.enhanced.SequenceStyleGenerator">
                <param name="optimizer">none</param>
                <param name="increment_size">1</param>
                <param name="sequence_name">seq_entity_list</param>
            </generator>
        </id>

        <property name="item" column="item" type="string" length="15"/>
    </class>
</hibernate-mapping>  

Item.class (list item superclass) [domain module]

public class Item extends Builder {

    private String item;

    public String getItem() {
        return item;
    }

    public void setItem(String item) {
        this.item = item;
    }
}  

RESULT:
During data pulling from database only entity1 list will be set. The superclass list will be null, because of access="field" in hbm file.

2nd. way

I removed access="field" attribute and started playing only with @AuditOverride annotations.
If I leave everything as in 1st. way , just remove the access attribute and the list in entity class, superclass will not be audited at all. So audit table fields will be null.
If I add additional @AuditOverride(forClass=Superclass.class) - all super class will be audited including the list even @AuditOverride(forClass=Superclass.class, name="list", isAudited=false) also is written. So I tried modify only:

Entity1.class (sublcass) [hibernate module]

/* @AuditOverrides(value = {
        @AuditOverride(forClass = Entity1.class),
        @AuditOverride(forClass = Superclass.class, name = "other", isAudited = true),
        @AuditOverride(forClass = Superclass.class, name = "list", isAudited = false)
* OR */
@AuditOverrides(value = {
        @AuditOverride(forClass = Entity1.class),
        @AuditOverride(forClass = Superclass.class),
        @AuditOverride(forClass = Superclass.class, name = "list", isAudited = false)
})
public class Entity1 extends Superclass {
}  

There is two options and both have same result.
RESULT:
The superclass is audited but the list is also will be audited. So that means that the audit relation ship will be created ( entity1_aud_entity2_aud ).

Conclusion

The 1st. way is not setting data to the superclass during data pulling. The 2nd. way - auditing all of superclass, while I need just a part of it to be audited. So the question will be:
Is there any other way to use annotations in subclass and audit only just a part of a superclass?

(make sure you read all the question information before the answering)
Thank you

Based on your question, you should be able to annotate your entities as follows:

@Entity
@Audited
@AuditOverrides({
  @AuditOverride(forClass = SuperClass.class, isAudited = true),
  @AuditOverride(forClass = SuperClass.class, name = "list", isAudited = false)
})
public class Entity1 extends SuperClass {
  // just put your entity1 attributes here, no need to duplicate anything
}

@Entity
@Audited
@AuditOverride(forClass = Item.class, isAudited = true)
public class Entity2 extends Item {
  // just put your entity2 attributes here, no need to duplicate anything
}

I've only used the @AuditOverride / @AuditOverrides annotations to control the auditing of the super types and their properties and @Audited to signal that entity type should be audited.

I also illustrate on Entity1 how you can mix various overrides in situations where you want to perhaps audit a majority of properties and exclude a subset or vice versa.

The end result here is that your Entity1_AUD table will contain all your properties from Entity1 and will also include all properties from your SuperClass class excluding your list attribute. Your Entity2_AUD table will contain all properties from Entity2 and the super class Item . Additionally, there will be no audited join-table between Entity1 and Entity2 for list .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM