问题描述
我正在使用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()
其余由字符串和数字组成的实体修订版也可以正常加载。在审核和查询其他没有继承结构的实体时,我也没有收到此错误。
实体_aud
,Job
和Task
的{{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 = 1
,revtype = 0
。将rev=1
,revtstmp=0
插入revinfo
表中。
另请参阅Safe Envers queries when the audit history is incomplete
说明因为集成envers之前存在的实体数据,所以审计表最初是空的。当您更新拥有对实体 B 的引用的实体 A 时,将在A_aud
中创建审计记录,但不会在B_aud
中创建审计记录。当查询 A 以进行修订时,它会尝试在空B_aud
中查找所引用的实体 B ,并产生一个EntityNotFoundException
,该实体被包裹起来在给定的GenericJDBCException
中。