难以使用Envers审核多对多关系 [英] Having difficulty using Envers to audit a many-to-many relation
问题描述
我想使用Envers来审计与嵌入式组件的多对多关系,但是我遇到了一个MappingException,说不支持ComponentType。这是堆栈跟踪的相关部分:
I'm wanting to use Envers to audit a many-to-many relation with an embedded component but I'm having trouble with a MappingException saying the the ComponentType is not supported. This is relevant portion of the stack trace:
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可以处理
我正在尝试做的事情。根据参考:
Reading the Envers reference, it appears that Envers can handle what I'm trying to do. According to the reference:
如果您想覆盖从@Mappedsuperclass或嵌入式组件继承的某些字段/属性的审核行为,您可以在组件的子类型或使用网站上应用@AuditOverride(s)注释。
If you'd like to override auditing behaviour of some fields/properties inherited from @Mappedsuperclass or in an embedded component, you can apply the @AuditOverride(s) annotation on the subtype or usage site of the component.
这是我的关联实体。您可以在类级别查看我尝试使用@AuditOverride的位置,以防止审核嵌入式组件。我也尝试在字段本身上使用注释。两者都没有区别。
Here's my association entity. You can see where I tried to use @AuditOverride at the class level to prevent auditing the embedded component. I also tried using the annotation on the field itself. Neither made a difference.
@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; }
...
}
最后,这是我的基本实体,为了完整性:
And finally, here is my base entity, for completeness:
@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参考资料并仔细阅读论坛,但信息
似乎很稀疏。关于这个的任何想法或指示?
I've read the Envers reference and perused the forum, but the information seems pretty sparse. Any ideas or pointers on this?
推荐答案
我通过丢弃可嵌入组件UserRolePk来解决这个问题,并且只是使用@JoinColumn例如
I resolved this by discarding the embeddable component, UserRolePk, and just going with @JoinColumn e.g.
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; }
...
}
这篇关于难以使用Envers审核多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!