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:
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.
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 ).
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.