【问题标题】:Having difficulty using Envers to audit a many-to-many relation难以使用 Envers 审计多对多关系
【发布时间】:2012-02-24 19:40:13
【问题描述】:

我想使用 Envers 来审核与嵌入式组件的多对多关系,但我遇到了 MappingException 问题,表示不支持 ComponentType。这是堆栈跟踪的相关部分:

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 参考并仔细阅读了论坛,但信息 似乎很稀疏。对此有何想法或建议?

【问题讨论】:

    标签: jakarta-ee jpa jpa-2.0 hibernate-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; }
    ...
    }
    

    【讨论】:

      【解决方案2】:

      我正在使用 Envers 4.1.3.Final,它肯定仍然存在这个错误:对于与 @Embedded 组件的关系,它记录数据库中的审计记录正确,但查询 API (@ 987654321@,就我而言)根本看不到它。它将返回更改对象的修订版 (MOD),但是当您查看包含对嵌入对象的引用的实际实体属性时,对于所有修订版,它始终为 null。

      我最终编写了一个解决方法来使用本机 SQL 查询更改的值(针对受影响的属性),因为我不想仅仅为了安抚一个有问题的插件而更改我的映射。

      【讨论】:

        猜你喜欢
        • 2013-02-08
        • 2011-09-13
        • 2011-05-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-21
        • 2013-08-27
        • 1970-01-01
        相关资源
        最近更新 更多