Hibernate启用“无法评估$ HibernateProxy $ .toString”

问题描述

我正在使用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的加载不正确。相反,休眠会给出一个

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

其余由字符串和数字组成的实体修订版也可以正常加载。在审核和查询其他没有继承结构的实体时,我也没有收到此错误

实体_audJobTask的{​​{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);
,

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

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

另请参阅Safe Envers queries when the audit history is incomplete

说明因为集成envers之前存在的实体数据,所以审计表最初是空的。当您更新拥有对实体 B 的引用的实体 A 时,将在A_aud中创建审计记录,但不会在B_aud中创建审计记录。当查询 A 以进行修订时,它会尝试在空B_aud中查找所引用的实体 B ,并产生一个EntityNotFoundException,该实体被包裹起来在给定的GenericJDBCException中。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...