1

Enversを使用して、埋め込みコンポーネントとの多対多の関係を監査したいのですが、ComponentTypeがサポートされていないというMappingExceptionで問題が発生しています。これは、スタックトレースの関連部分です。

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のリファレンスを読み、フォーラムを熟読しましたが、情報はかなりまばらに見えます。これに関するアイデアや指針はありますか?

4

2 に答える 2

1

私はEnvers4.1.3.Finalを使用していますが、間違いなくこのバグがあります。@ Embeddedコンポーネントとの関係では、監査レコードがデータベースに正しくログに記録されますが、クエリAPI(forRevisionsOfEntity私の場合)は単にそれを認識しません。 。変更されたオブジェクトのリビジョン(MOD)を返しますが、埋め込みオブジェクトへの参照を保持する実際のエンティティプロパティを調べると、すべてのリビジョンで常にnullになります。

バグのあるプラグインを和らげるためだけにマッピングを変更する気がなかったので、(影響を受けるプロパティの)ネイティブSQLを使用して変更された値をクエリするための回避策を作成することになりました。

于 2012-09-11T09:57:27.690 に答える
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; }
...
}
于 2012-08-17T11:36:54.630 に答える