2015-12-15 11 views
13

に@Audited私は、エンティティ子供を拡張子供、クラシックな継承の永続性を持っています。クラスは抽象であり、子供ではありません。休止Envers:サブクラス

私は監査したい子供の間にこのエンティティは私のコントロール下にあります。また、監査する必要のない他の多くのサブクラスがあります。階層全体の継承ストラテジーはJOINEDです。

だから私は@AuditOverride(forClass = Parent.class)@Audited、さらにと子供を注釈を付けています。私は何を得る

このエラーです:

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

ちなみに、私はenversに4.0.1.Finalバージョンを使用しています。

どのように私はこれを達成することができます知っていますか? 私は@AuditOverrideの除去、子供クラスに@Auditedを削除しようとした、@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); 
    } 

} 

そして最後に、ここポテトです:

Potato image

は、事前にありがとうございます!

+0

ほとんどの場合、これは '休止状態のバグ'です。参照:https://forum.hibernate.org/viewtopic.php?p=2489543 – Andremoniy

+0

このようなマッピングは、Hibernate 5で正常に動作します.1つの解決策は、休止状態を更新することです。 –

答えて

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.

ランタイムでそれらに注釈を付けることが示唆されました。しかし、この決定はあなたの場合には不適切です。親クラスに手動で注釈を付けることができます。

あなたは親クラスが監査されたくない場合は、回避策として、あなたはParentがちょうどその子孫になりながら、本質的に、Parentと同じになりますMappedSuperClass抽象ベースを作成しようとすることができ、その後、Childクラスのために再び@AuditOverrideを試してみてください。 Parentクラスの監査を「スキップ」し、Childのために行うことが可能です。