最后的方法是否阻止Hibernate为这样的实体创建代理? [英] Does a final method prevent Hibernate from creating a proxy for such an entity?

查看:102
本文介绍了最后的方法是否阻止Hibernate为这样的实体创建代理?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Hibernate使用代理来启用集合的延迟加载甚至单端关联。根据Hibernate(3.6.5)的参考文档( Section 21.1.3,单端关联代理),如果Hibernate包含任何最终方法

我的问题是,这个限制仅适用于持久字段的getters / setters还是真的适用于实体类中的任何方法?所以,像这样的方法:

  public final String toString(){
return this.getClass() .getSimpleName()+ id;
}

确实会阻止为此实体创建(CGLIB或Javassist)代理?
如果使用基于场地或财产访问权限,这有什么关系?由于CGLIB被Javassist替代,它是否提供了这个方向的更多功能?



我喜欢在我的实体层次结构中使用继承,因此需要定义一些最终方法,例如
,以防止子类覆盖这些方法。



提前感谢!

解决方案

在Hibernate邮件列表的帮助下(谢谢Emmanuel Bernardt!),我可以回答我自己的问题,摘要是:

Final方法不会阻止Hibernate创建代理,但除非这些方法不使用实体的任何状态,否则这是非常不可取的。



一些背景信息:Hibernate不使用字节码增强,也不使用cglib,也不使用Javassist,所以为了让代理懒惰地初始化其目标实体,它必须拦截任何可能使用该目标实体状态的方法。
现在完全可以拥有这样的最终方法

  public final doSomething(String a,Integer b){ 
//使用只有a和b的复杂东西(没有实例成员访问!)
}

,但只要此方法直接使用任何持久字段或通过另一个实例方法,这将绕过代理,从而导致意外行为。



作为旁注,这与你为什么不直接访问其他实例的字段的原因相同,例如在实体 equals 方法中:

  // XXX错误代码! 
public boolean equals(Object o){
if(this == o)return true;
if(!(o instanceof Profile))返回false;
简介简介=(简介)o;
// XXX这会绕过一个可能的代理,请改用profile.getName()!
return(name == null?profile.name == null:name.equals(profile.name));
}


Hibernate uses proxies to enable lazy loading of collections and even single-ended associations. According to Hibernate's (3.6.5) reference documentaion (Section 21.1.3, Single-ended association proxies), such a proxy can't be constructed by Hibernate if it contains "any final methods".
My question is, does this restriction apply to getters/setters of persistent fields only or really to any method in an entity class? So, does a method like this one:

public final String toString() {
   return this.getClass().getSimpleName() + id;
}

really prevent the creation of a (CGLIB or Javassist) proxy for this entity? Does it matter if field-based or property access is used? Since CGLIB was replaced by Javassist, does this provide any more features in this direction?

I like to use inheritance in my entity hierarchy and hence the requirement to define some final methods, for example, in the base class to prevent subclasses from overriding those methods.

thanks in advance!

解决方案

By the help of the Hibernate mailing list (thanks Emmanuel Bernardt!) I'm able to answer my own question, the summary is:
Final methods do not prevent Hibernate from creating a proxy in general but unless those methods don't use any state of the entity this is highly inadvisable.

Some background information: Hibernate doesn't use bytecode enhancement neither with cglib nor with Javassist so, in order for a proxy to initialize its target entity lazily it has to intercept any method which may use the state of that target entity. Now it's perfectly ok to have a final method like this

public final doSomething(String a, Integer b ) {
  // do complicated stuff using only a and b (no instance members accessed!)
}

but as soon as this method uses any persistent field directly or through another instance method this would bypass the proxy and thus lead to unexpected behaviour.

As a sidenote this is the same reason why you should not access fields of other instances directly, for example in an entities equals method:

// 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));
}

这篇关于最后的方法是否阻止Hibernate为这样的实体创建代理?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆