2012-02-02 33 views
1

我想要使用Envers來審計與嵌入式組件的多對多關係,但我遇到了MappingException的問題,說ComponentType是不支持。這是堆棧跟蹤的相關部分:難以使用Envers來審計多對多關係

Caused by: org.hibernate.MappingException: Type not supported: org.hibernate.type.ComponentType 
     at org.hibernate.envers.configuration.metadata.IdMetadataGenerator.addIdProperties(IdMetadataGenerator.java:74) 
     at org.hibernate.envers.configuration.metadata.IdMetadataGenerator.addId(IdMetadataGenerator.java:105) 
     at org.hibernate.envers.configuration.metadata.AuditMetadataGenerator.generateFirstPass(AuditMetadataGenerator.java:413) 
     at org.hibernate.envers.configuration.EntitiesConfigurator.configure(EntitiesConfigurator.java:101) 
     at org.hibernate.envers.configuration.AuditConfiguration.<init>(AuditConfiguration.java:103) 
     at org.hibernate.envers.configuration.AuditConfiguration.getFor(AuditConfiguration.java:135) 
     at org.hibernate.envers.event.EnversIntegrator.integrate(EnversIntegrator.java:63) 
     at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:295) 
     at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1737) 
     at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:76) 
     at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905) 

讀Envers參考,似乎Envers可以處理 我想要做的事。據參考:

如果你想覆蓋從@MappedSuperclass或嵌入式組件繼承了某些字段/屬性的審計行爲,可以適用於亞型或使用該@AuditOverride(S)註釋組件的位置。

這是我的關聯實體。您可以在類級別上看到我嘗試使用@AuditOverride的位置,以防止審覈嵌入的組件。我也嘗試在字段本身上使用註釋。兩者都沒有改變。

@Audited 
// @AuditOverride(name = "pk", isAudited = false) <===== Didn't help 
@Table(name = "user_role") 
@javax.persistence.Entity 
@AssociationOverrides 
(
    { 
    @AssociationOverride 
     (name = "pk.user", joinColumns = @JoinColumn(name = "id")), 
    @AssociationOverride 
     (name = "pk.role", joinColumns = @JoinColumn(name = "id")) 
    } 
) 
public class UserRole extends Entity<UserRole> 
{ 
    private static final long serialVersionUID = 1L; 

    private Date expirationDate; 
    private UserRolePk pk = new UserRolePk(); 

    public UserRole() {} 

    // @AuditOverride(name = "pk", isAudited = false) <== Didn't help 
    @EmbeddedId 
    public UserRolePk getPk() { return pk; } 

    @Transient 
    public User getUser() { return getPk().getUser(); } 

    @Transient 
    public Role getRole() { return getPk().getRole(); } 
... 
} 

這裏的用戶實體:

@Audited 
@Table(name = "applicationuser") 
@javax.persistence.Entity 
public class User extends Entity<User> 
{ 
    private static final long serialVersionUID = 1L; 
    private String firstName; 
    private String lastName; 
    private String email; 
    private Set<UserRole> userRoles = new HashSet<UserRole>(0); 

    @OneToMany(fetch = FetchType.LAZY, cascade=CascadeType.ALL, 
     mappedBy = "pk.user", orphanRemoval = true) 

    public Set<UserRole> getUserRoles() { return userRoles; } 
... 
} 

這裏的角色實體:

@Audited 
@Table(name = "role") 
@javax.persistence.Entity 
public class Role extends Entity<Role> 
{ 
    private static final long serialVersionUID = 1L; 
    private String name; 
    private String label; 
    private Set<UserRole> userRoles = new HashSet<UserRole>(0); 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "pk.role", 
     cascade=CascadeType.ALL, orphanRemoval = true) 

    public Set<UserRole> getUserRoles() { return userRoles; } 
... 
} 

這裏的嵌入式組件:

@Embeddable 
public class UserRolePk implements Serializable 
{ 
    private static final long serialVersionUID = 1L; 

    private User user; 
    private Role role; 

    @ManyToOne 
    public User getUser() { return user; } 

    @ManyToOne 
    public Role getRole() { return role; } 
... 
} 

最後,這裏是我的基地實體,爲了完整性:

@MappedSuperclass() 
public abstract class Entity<X extends Entity<X>> 
    implements Comparable<X>, Serializable 
{ 
    private static final long serialVersionUID = 1L; 
    private Long id; 
    private Timestamp timestamp; 
... 
} 

我讀過的Envers參考,並仔細閱讀論壇,但信息 似乎很稀疏。任何想法或指針?

回答

1

我通過丟棄可嵌入組件UserRolePk,然後使用@JoinColumn來解決這個問題,例如,

public class UserRole extends Entity<UserRole> 
{ 
    private User user; 
    private Role role; 

    public UserRole() {} 

    @ManyToOne(fetch=FetchType.EAGER, optional=false) 
    @JoinColumn(name="userid", referencedColumnName = "id", insertable=false, updatable=false) 
    // XmlTransient used to prevent the following exception when JAXB marshals this into XML: 
    // com.sun.istack.SAXException2: A cycle is detected in the object graph. This will cause 
    // infinitely deep XML: 
    @XmlTransient 
    public User getUser() { return this.user; } 

    @ManyToOne(fetch=FetchType.EAGER, optional=false) 
    @JoinColumn(name="roleid", referencedColumnName = "id", insertable=false, updatable=false) 
    public Role getRole() { return this.role; } 
... 
} 
1

我使用Envers 4.1.3.Final,它肯定還是有這個錯誤:爲給@Embedded組件它日誌審計記錄正確的數據庫,但查詢API forRevisionsOfEntity關係(,在我的情況)根本沒有看到它。它會爲已更改的對象返回一個修訂(MOD),但是當您查看保存對嵌入對象的引用的實際實體屬性時,對於所有修訂,它始終爲空。

我最終編寫了一個解決方法,用原生SQL查詢更改後的值(對於受影響的屬性),因爲我不想改變我的映射只是爲了安裝錯誤的插件。