【问题标题】:Hibernate envers "cannot evaluate $HibernateProxy$.toString()"Hibernate envers“无法评估 $HibernateProxy$.toString()”
【发布时间】:2020-12-03 08:26:33
【问题描述】:

我正在使用 envers 来审核我的实体。我的代码看起来有点像这样

@Audited( targetAuditMode = RelationTargetAuditMode.NOT_AUDITED )
@AuditOverride( forClass = Task.class, isAudited = true )
public class Job extends Task
{...}

@Inheritance( strategy = InheritanceType.JOINED )
@Audited( targetAuditMode = RelationTargetAuditMode.NOT_AUDITED )
public class Task
{ 
    ...
    @ManyToOne( fetch = FetchType.LAZY )
    @LazyToOne( value = LazyToOneOption.NO_PROXY )
    @Fetch( value = FetchMode.SELECT )
    @JoinColumn( nam = "id_util" )
    @Audited( targetAuditMode = RelationTargetAuditMode.AUDITED )
    private Utility utility;
}

@Entity
@DynamicInsert
@DynamicUpdate
@Audited( targetAuditMode = RelationTargetAuditMode.NOT_AUDITED )
public class Utility
{
    @Override
    public String toString()
    {
        StringBuilder builder = new StringBuilder();
        builder.append( this.getClass().getName() ).append( "@" ).append( getId() );
        builder.append( "[" );
        appendAttributeValues( builder );
        builder.append( "]" );
        return builder.toString();
    }

    public Long getId()
    {
        return id;
    }
}

当我尝试获取某个job 实体的修订版时,utility 字段未正确加载。相反,hibernate 给出了一个

Method threw 'org.hibernate.exception.GenericJDBCException' exception. Cannot evaluate Utility$HibernateProxy$9GVDBIUC.toString()

由字符串和数字组成的实体修订的其余部分加载得很好。在审核和查询没有继承结构的其他实体时,我也没有收到此错误。

实体JobTaskUtility_aud 表均已正确填写。什么可能导致此错误?

【问题讨论】:

  • 您能否也包含Utility 实体的代码?谢谢
  • 该实用程序包含简单类型和对与此问题不同的其他实体的引用。我添加了我正在使用的注释。
  • 拜托,如果有的话,您能否至少包含实体的toString 方法定义?
  • toString() 包括
  • 谢谢。而方法appendAttributeValues的定义是什么?我很抱歉地问,这个问题可能与方法 ```toString` 的实现中的一些代码有关。例如,假设您引用了一个不存在的关系或类似的东西。如果不是这样,我们可以考虑其他原因。

标签: java hibernate hibernate-envers


【解决方案1】:

在使用链接对象之前,您应该“物化”由休眠创建的代理对象,就像在这个答案中所说:https://stackoverflow.com/a/2216603/3744622

Hibernate.initialize(entity);
if (entity instanceof HibernateProxy) {
    entity = (T) ((HibernateProxy) entity).getHibernateLazyInitializer()
        .getImplementation();
}
return entity;

或者,例如,使用特殊方法unproxy

Object unproxiedObject = Hibernate.unproxy(proxiedObject);

【讨论】:

    【解决方案2】:

    TLDR 原因是审计数据不一致。当您开始审核已经存在的实体及其关系时,就会发生这种情况。

    解决方案 复制aud对应表中的所有实体数据rev = 1,revtype = 0。将rev=1revtstmp=0 插入到revinfo 表中。

    另见Safe Envers queries when the audit history is incomplete

    说明 因为实体数据在envers集成之前就已经存在,所以审计表一开始是空的。当您更新拥有对实体 B 的引用的实体 A 时,会在 A_aud 但不会在 B_aud 中创建审计记录。当向 A 查询修订时,它会尝试在 emtpy B_aud 中查找引用的实体 B 并生成一个 EntityNotFoundException,它包含在给定的 @ 中987654332@.

    【讨论】:

    • 你能描述一下如何解决这个问题吗?
    • 添加了快速解决方案。在链接的休眠论坛帖子中对其进行了进一步描述。
    猜你喜欢
    • 1970-01-01
    • 2018-05-07
    • 2019-03-30
    • 2020-01-26
    • 2023-03-17
    • 1970-01-01
    • 2017-04-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多