如何只审计hibernate中超类的一部分?

时间:2018-01-23 10:00:43

标签: java hibernate jpa hibernate-envers hibernate-annotations

我想问一下如何使用h @AuditOverride@Audited之类的hibernate注释来审核实体的超类的一部分。现在,我正在使用hibernate 5.2.12版本 我只能在sublcass中使用的注释,因为超类在其他模块中,不应该对子模块有任何了解。
超类包含一个List<Items>,我不希望它会被审核。因为当我使用one-to-many关系时,我不希望hibernate会创建审计关系表,例如 entity1_aud_entity2_aud 。我只需要 entity1_aud entity2_aud 表 为了拒绝审计关系表,我找到了两种方法,但所有方法都不完全正确:

第一。方式

我将list变量和setter / getters复制到实体( subclass )。在列表变量上面我写了@NotAudited注释。为了使该注释有效,我在access="field"文件中设置了hbm属性。所以hibernate不使用setter和getter来访问变量,所以超级类的值不是在数据提取期间设置
我还创建了列表实体,我在其中编写@AuditOverrides(value={@AuditOverride(forClass=Entity2.class), @AuditOverride(forClass=Item.class)})。这些注释为列表实体创建审计表。因此,这种审计方式的完整代码是:
Entity1.class(主要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 [域模块]

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(列表项子类)[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(列表项超类)[域模块]

public class Item extends Builder {

    private String item;

    public String getItem() {
        return item;
    }

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

结果:
在从数据库中提取数据期间,仅设置 entity1 列表。由于hbm文件中的access="field",超类列表将为null。

第二。方式

我删除了access="field"属性,并开始只使用@AuditOverride注释 如果我把所有内容保留在 1st中。方式,只需删除access属性和实体类中的列表,根本不会审计超类。因此审计表字段将为空 如果我添加额外的@AuditOverride(forClass=Superclass.class) - 所有超级类都将被审计,包括列表甚至@AuditOverride(forClass=Superclass.class, name="list", isAudited=false)也被写入。所以我只尝试修改:

Entity1.class(s​​ublcass)[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 {
}  

有两个选项,两者都有相同的结果 的结果:
超级类别已经过审计,但列表也将被审计。这意味着将创建审计关系( entity1_aud_entity2_aud )。

结论

第1名。方法是在数据提取期间不将数据设置到超类。第二个。方式 - 审计所有超类,而我只需要审计其中的一部分。所以问题是:
是否有其他方法可以在子类中使用注释并仅审核超类的一部分?

(确保在回答之前阅读所有问题信息)
谢谢

1 个答案:

答案 0 :(得分:3)

根据您的问题,您应该能够按如下方式注释您的实体:

@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
}

我只使用@AuditOverride / @AuditOverrides注释来控制超类型及其属性的审核,并@Audited表示应审核实体类型。

我还在Entity1上说明了如何在想要审核大多数属性并排除子集的情况下混合各种覆盖,反之亦然。

此处的最终结果是,您的Entity1_AUD表格将包含Entity1中的所有媒体资源,并且还会包含SuperClass课程中除list属性之外的所有媒体资源。您的Entity2_AUD表将包含Entity2和超类Item的所有属性。此外,对于Entity1Entity2list之间不会有经过审核的联接表。