2015-12-15 45 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做审计。