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
hbm.xml
files. The second point is that you offered the same option as my 2nd. way, becauseisAudited = true
attribute is by default true and it can be not specified on this case. How ever, after long messing up I found the way that everything works fine. That means your option (and mine 2nd. way) is correct. And all I need to do to just leaveaccess="field"
attribute inentity1.hbm.xml
file. So then annotation@AuditOverride(forClass = SuperClass.class, name = "list", isAudited = false)
will work correctly. – Little