【问题标题】:Hibernate Envers and "Javassist Enhancement failed" ExceptionHibernate Envers 和“Javassist 增强失败”异常
【发布时间】:2011-11-08 13:02:25
【问题描述】:

我们使用的是Hibernate Envers,遇到以下情况:

一个类BusinessObjectType和一个类Identity引用BusinessObjectType

@Entity
@Table( name = "ID_IDENTITY" )
@Audited
public class Identity {

    @ManyToOne
    @JoinColumn( name = "BO_TYPE_ID" )
    @IndexColumn( name = "INDEX_BO_BO_TYPE" )
    private BusinessObjectType businessObjectType;

    […]

}

然后我们使用以下命令查询所有版本的 Identity:

AuditQuery auditQuery = auditReader.createQuery().forRevisionsOfEntity(
    Identity.class,
    false,
    true );
auditQuery.add( AuditEntity.id().eq( dbid ) );

@SuppressWarnings( "unchecked" )
List< Object[]> history = (List< Object[]>) auditQuery.getResultList();

如果存储的身份没有BusinessObjectType(即businessObjectType 为空),则一切都像魅力一样。

如果身份有 businessObjectType != null,我们会收到“Javassist Enhancement failed”异常:

Javassist Enhancement failed: ch.ethz.id.wai.baseclasses.BusinessObjectType

该错误似乎与 Envers 尝试实例化 BusinessObjectType 相关,但我真的不知道问题出在哪里(如果我们不使用 AuditQuery,Hibernate 对这两个对象都没有问题)。

异常的原因是

java.lang.InstantiationException: ch.ethz.id.wai.baseclasses.BusinessObjectType_$$_javassist_49

没有堆栈跟踪。

关于问题可能是什么的任何提示?

【问题讨论】:

    标签: hibernate hibernate-envers


    【解决方案1】:

    这发生在以下类 JavassistLazyInitializer 基于 Javassist 的惰性初始化器代理中。

    如果不查看完整源代码,很难发表评论,但您可以尝试以下选项。

    • 关闭 @ManyToOne 关系的延迟加载 [这是一个设计决策,因此请注意它是否不适合整体解决方案]
    • 为导致问题的实体提供默认的公共构造函数[这更容易]
    • 如果不是真的需要,通过将 hibernate.bytecode.use_reflection_optimizer 属性设置为 false 来关闭反射优化

    让我们知道这是否有帮助

    【讨论】:

    • 获取是默认值:SELECT。构造函数不是公开的。谢谢。我仍然需要理解为什么 Envers 想要实例化的不仅仅是简单的 Hibernate。
    • 为什么默认构造函数必须是public?我看到一个可能相互矛盾的答案here
    【解决方案2】:

    要获取有关异常的更多信息,请使用 IDE 的调试工具为 java.lang.InstantiationException 设置异常断点,以便在发生基础异常时停止执行。这应该会向您显示完整的堆栈跟踪,并允许您检查堆栈上的所有变量。

    如果我不得不猜测,我的第一个怀疑是自从与 BusinessObjectType 没有映射为惰性,普通休眠不会尝试为该类创建代理。相比之下,Envers 似乎确实如此。代理是在运行时生成的覆盖所有公共方法的子类。因此,无论是类还是任何公共方法(继承自Object 的方法除外)都不能声明为final,并且子类必须可以访问默认构造函数。

    【讨论】:

    • 我有同样的嫌疑:Envers 试图获取更多(否则我不会有错误)。一个问题是:为什么?我怎样才能避免它?另一方面,BusinessObjectType 有一个默认的公共构造函数并且没有最终字段。使用普通的 Envers 可以毫无问题地获取它。
    • ...也没有最终方法?我对 Envers 的内部结构知之甚少,无法进一步猜测。这就是为什么我会开始调试以获取更多信息。
    • 实际上我没有注意到在最后一次更改测试期间我将构造函数重新设为私有。顺便说一句:使用公共构造函数 final 方法似乎有效。谢谢!
    • 我将赏金授予 user3965072,因为他是第一个......我没有机会在他回答后立即进行测试(周末:-)
    猜你喜欢
    • 2012-09-01
    • 1970-01-01
    • 2021-05-19
    • 2014-12-02
    • 1970-01-01
    • 2014-04-17
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    相关资源
    最近更新 更多