簡體   English   中英

Hibernate Envers:@Audited 在子類上

[英]Hibernate Envers: @Audited on a subclass

我有實體ParentChild的經典繼承持久性,其中Child擴展Parent Parent類是抽象的,而Child不是。

我想審計Child 這個實體在我的控制之下,而Parent不在。 此外,它還有許多其他不需要審計的子類。 整個層次結構的繼承策略是JOINED

所以我用@Audited@AuditOverride(forClass = Parent.class)注釋了Child

我得到的是這個錯誤:

“org.hibernate.MappingException: 實體 'Child' 被審計,但它的超類:'Parent' 不是。”

順便說一下,我使用的是 envers 4.0.1.Final 版本。

有誰知道我怎樣才能做到這一點? 我試着在兒童類刪除@Audited,消除@AuditOverride,@Audited注釋使用過時auditParents,但似乎沒有任何工作。

這是父實體:

@Entity
@Table(name = "parent")
@Inheritance(strategy = InheritanceType.JOINED)
@DiscriminatorColumn(name = "type")
public class Parent {
    public Parent() {
        super();
    }

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "base_id", unique = true, nullable = false)
    private Integer baseId;

    @Column(name = "base_field")
    private String baseField;

    @Column(name = "type")
    private String type;

    // getters and setters
}

這是我的孩子實體:

@Entity
@Table(name = "child")
@DiscriminatorValue("CHILD")
@Audited
@AuditOverride(forClass = Parent.class)
public class Child extends Parent {
    public Child() {
        super();
    }

    @Column(name = "child_field")
    private String childField;

    // getters and setters
}

這是實體:

CREATE  TABLE `REVINFO` (
  `REV` BIGINT NOT NULL AUTO_INCREMENT,
  `REVTSTMP` BIGINT NULL ,
  PRIMARY KEY (`REV`)
);

CREATE TABLE `parent` (
  `base_id` int(11) NOT NULL AUTO_INCREMENT,
  `base_field` varchar(45) DEFAULT NULL,
  `type` varchar(45) NOT NULL,
  PRIMARY KEY (`base_id`)
);

CREATE TABLE `child` (
  `base_id` int(11) NOT NULL AUTO_INCREMENT,
  `child_field` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`base_id`)
);

CREATE TABLE `child_AUD` (
  `base_id` int(11) NOT NULL,
  `REV` BIGINT NOT NULL,
  `REVTYPE` tinyint(2) DEFAULT NULL,
  `child_field` varchar(45) DEFAULT NULL,
  PRIMARY KEY (`base_id`,`REV`)
);

這是一個測試用例:

public class EnversInheritanceTest extends AbstractJUnit4SpringContextTests {

    @Inject
    private EntityManagerFactory entityManagerFactory;

    private EntityManager entityManager;

    @Test
    public void inheritanceTest() {

        this.entityManager = this.entityManagerFactory.createEntityManager();

        Child child = this.createChild();
        this.saveChild(child);

        this.modifyChild(child);
        this.saveChild(child);

        Assert.assertNotNull(child.getBaseId());
        Assert.assertNotNull(this.getOriginalRevision(child.getBaseId()));

        Child original = this.getOriginalChild(child.getBaseId());

        Assert.assertNotNull(original);
        Assert.assertEquals("child", original.getChildField());

    }

    private Child createChild() {
        Child child = new Child();
        child.setBaseField("base");
        child.setChildField("child");
        child.setType("CHILD");
        return child;
    }

    private void saveChild(Child child) {
        this.entityManager.getTransaction().begin();
        this.entityManager.persist(child);
        // We need to commit in order to trigger Envers magic
        this.entityManager.getTransaction().commit();
    }

    private void modifyChild(Child child) {
        child.setBaseField("foo");
        child.setChildField("bar");
    }

    public Child getOriginalChild(Serializable id) {
        Object queryResult = this.getAuditReader().createQuery()
                .forEntitiesAtRevision(Child.class, this.getOriginalRevision(id))
                .add(AuditEntity.id().eq(id))
                .getSingleResult();
        return (Child) queryResult;
    }

    private Number getOriginalRevision(Serializable id) {
        AuditProjection minRevNumberAuditProjection = AuditEntity.revisionNumber().min();
        Number revision = (Number) this.getAuditReader().createQuery()
                .forRevisionsOfEntity(Child.class, false, false)
                .add(AuditEntity.id().eq(id))
                .addProjection(minRevNumberAuditProjection)
                .getSingleResult();

        return revision;
    }

    private AuditReader getAuditReader() {
        return AuditReaderFactory.get(this.entityManager);
    }

}

先感謝您!

一個很好的問題。 2013年在jboss開發者論壇上也有過同樣的討論 答案來自Hibernate Enver 的創始人和項目負責人

您必須以某種方式審核超類。 目前,除了注釋之外,沒有其他方法可以指定此類元數據。

在同一個討論樹中,根據父類也需要注釋的事實,建議在運行時對其進行注釋。 但是這個決定似乎很丑陋,不適合您的情況:您可以手動注釋父類。

作為一種解決方法,如果您不想審核父類,您可以嘗試創建一個基本抽象MappedSuperClass ,它基本上與Parent相同,而Parent將只是它的后代,然后再次嘗試放置@AuditOverride對於Child類。 它可能會“跳過”對Parent類的審計,而對Child進行審計。

嘗試使用 @Audited 注釋標記父類和子類,但對於父類添加 @Audited(targetAuditMode = NOT_AUDITED)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM