2015-12-15 43 views
13

我有實體家長兒童,其中兒童延伸家長經典傳承的持久性。類是抽象的,而不是。休眠Envers:@Audited上一個子類

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

因此,我已註釋的兒童@Audited和另外用@AuditOverride(forClass = Parent.class)

我得到的是這樣的錯誤:

"org.hibernate.MappingException: Entity 'Child' is audited, but its superclass: 'Parent' is not."

順便說一句,我使用envers 4.0.1.Final版本。

有誰知道我該如何做到這一點? 我試着刪除@Audited兒童類,除去@AuditOverride,使用過時auditParents@Audited註釋,但似乎沒有任何工作。

這是父實體:

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

} 

最後這裏的土豆:

Potato image

預先感謝您!

+0

很可能是'hibernate-envers'中的一個bug。請參閱:https://forum.hibernate.org/viewtopic.php?p=2489543 – Andremoniy

+0

這種映射在hibernate 5中工作正常。一種解決方案是更新休眠。 –

回答

2

非常好的問題。在2013年,jboss開發者論壇上有same discussion。而答案是從the founder and project lead of Hibernate Enver

You would have to get the superclass audited somehow. Currently there's no other way to specify such metadata except for annotations.

在同樣的討論樹根據事實,父類也應註釋有建議註釋它們在運行時。但是這個決定看起來很醜,並且不適合你的情況:你可以手動註釋父類。

至於解決方法,如果你不想被審計的父類,則可以嘗試創建抽象基MappedSuperClass基本上將是一樣Parent,而Parent將只是它的後代,然後再次嘗試@AuditOverrideChild類。它有可能會「跳過」Parent級別的審計,併爲Child做審計。