Hibernate使用代理来启用延迟加载集合甚至单端关联.根据Hibernate的(3.6.5)参考文档(第21.1.3节,单端关联代理),如果Hibernate包含" 任何最终方法 ",则不能构造这样的代理.
我的问题是,这个限制是仅适用于持久字段的getter/setter还是实际上适用于实体类中的任何方法?那么,这样的方法是这样的:
public final String toString() {
return this.getClass().getSimpleName() + id;
}
Run Code Online (Sandbox Code Playgroud)
真的阻止为这个实体创建(CGLIB或Javassist)代理吗?使用基于字段或属性访问是否重要?由于CGLIB被Javassist取代,这是否提供了这方面的更多功能?
我喜欢在我的实体层次结构中使用继承,因此需要定义一些最终方法,例如,在基类中,以防止子类覆盖这些方法.
提前致谢!
在Hibernate邮件列表的帮助下(感谢Emmanuel Bernardt!)我能够回答我自己的问题,总结是:
最终方法不会阻止Hibernate创建代理,但除非这些方法不使用任何状态这个实体是非常不可取的.
一些背景信息:Hibernate既不使用cglib也不使用字节码增强,因此,为了让代理懒惰地初始化其目标实体,它必须拦截任何可能使用该目标实体的状态的方法.现在完全可以拥有这样的最终方法
public final doSomething(String a, Integer b ) {
// do complicated stuff using only a and b (no instance members accessed!)
}
Run Code Online (Sandbox Code Playgroud)
但是一旦此方法直接或通过另一个实例方法使用任何持久字段,这将绕过代理,从而导致意外行为.
作为旁注,这与您不应直接访问其他实例的字段的原因相同,例如在实体equals方法中:
// XXX bad code!
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Profile)) return false;
Profile profile = (Profile) o;
// XXX this bypasses a possible proxy, use profile.getName() instead!
return (name == null ? profile.name == null : name.equals(profile.name));
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2301 次 |
| 最近记录: |