java 为什么休眠返回代理对象?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2594804/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is hibernate returning a proxy object?
提问by rhu
I have a service method that calls a DAO which then returns an object from the database. This method is called from numerous parts of the system. However, one particular method is getting a return type of ObjectClass_$$_javassist_somenumber as the type. Which is throwing things off. I call the service method exactly the same as everywhere else, so why would hibernate return the proxy as opposed to the natural object?
我有一个调用 DAO 的服务方法,然后从数据库返回一个对象。从系统的许多部分调用此方法。但是,一种特殊的方法是获取 ObjectClass_$$_javassist_somenumber 的返回类型作为类型。这是扔东西。我调用的服务方法和其他地方完全一样,那么为什么 hibernate 会返回代理而不是自然对象呢?
I know there are ways to expose the "proxied" object, but I don't feel like I should have to do that.
我知道有一些方法可以公开“代理”对象,但我觉得我不应该这样做。
The query is simply
查询很简单
hibernateTemplate.find("from User u where u.username = ?", username)
I am using hibernate 3.3 btw.
顺便说一句,我正在使用休眠 3.3。
回答by rhu
It is a proxied object in order to support lazy loading; basically as soon as you reference a child or lookup object via the accessor/getter methods, if the linked entity is not in the session cache, then the proxy code will go off to the database and load the linked object. It uses javassistto effectively dynamically generate sub-classed implementations of your objects (although I think it can be configured to use CGLIBtoo).
它是一个代理对象,以支持延迟加载;基本上,只要您通过访问器/获取器方法引用子对象或查找对象,如果链接实体不在会话缓存中,则代理代码将转到数据库并加载链接对象。它使用javassist有效地动态生成对象的子类实现(尽管我认为它也可以配置为使用CGLIB)。
If it weren't proxied in this way it would be nigh-on impossible to implement seamless lazy loading.
如果不以这种方式进行代理,则几乎不可能实现无缝延迟加载。
I can't remember off the top-of-my-head whether if you use eager loading then whether the natural object would be returned instead. I wouldn't generally recommend using eager loading though especially if you have lots of linked child entities, as it can soon be a huge performance bottleneck as it will suck in every linked object into memory.
我不记得是否如果您使用预先加载,那么是否会返回自然对象。我通常不建议使用预先加载,特别是如果你有很多链接的子实体,因为它很快就会成为一个巨大的性能瓶颈,因为它会将每个链接对象吸入内存。
Also, if you need to discriminate on the class type, rather than using obj.getClass(), use Hibernate.getClass(obj)which will give you back the natural object class regardless of whether it is proxed or not: see the Hibernate API Javadocs here.
此外,如果您需要区分类类型,而不是使用obj.getClass(), 使用Hibernate.getClass(obj)which 将返回自然对象类,无论它是否被代理:请参阅此处的 Hibernate API Javadocs 。
回答by Lukasz Frankowski
In my opinion this expression:
在我看来这个表达:
hibernateTemplate.find("from User u where u.username = ?", username)
Should always return POJO, not a proxy. This is because standard HQL/criteria returns non-proxied object, but objects of your original entity classes. This is different from lazy associationsfetching:
应该总是返回 POJO,而不是代理。这是因为标准 HQL/标准返回非代理对象,而是原始实体类的对象。这与懒惰的关联获取不同:
@Entity
class X {
@ManyToOne(fetch = FetchType.LAZY)
private User user;
}
Getting Xobject from the db here, we will have a lazy proxy in X.userfield (a proxied Userinstance).
X从这里的 db获取对象,我们将在X.user字段(代理User实例)中有一个惰性代理。
Now, it happens that doing from User where [...]you sometimes have POJO and sometimes proxy object. Usually this is because in some executions Userobject was first fetched from the db through associations (from X where [...]query was called first in given hibernate session). Having already (proxied) Userinstance, hibernate will reuse this instance even for your plain queries like from User where [...].
现在,碰巧from User where [...]你有时有 POJO,有时有代理对象。通常这是因为在某些执行中User对象首先通过关联从数据库中获取(from X where [...]查询在给定的休眠会话中首先被调用)。已经(代理)User实例,即使对于像from User where [...].
回答by openCage
Hibernate returns proxies if not all members are resolved, i.e. the object is not complete. This is often a desired feature to improve performance and is (I think) the default setting in hibernate.
如果不是所有成员都被解析,Hibernate 将返回代理,即对象不完整。这通常是提高性能的理想功能,并且(我认为)是休眠中的默认设置。
If you do not want proxies you can suppress lazy loading in the hbm.xml file, i.e. use eager loading. Please check the hibernate docs for the exact syntax.
如果您不需要代理,您可以在 hbm.xml 文件中禁止延迟加载,即使用预先加载。请检查休眠文档以获取确切的语法。
To use the proxy object just never access a member directly but only via getter, even within member functions. Hibernate magic fills in the member when you get it. This way you never have to expose the object. Also don't use instanceof on potential proxy objects. But this is a code smell anyway.
使用代理对象永远不会直接访问成员,而只能通过 getter 访问,即使在成员函数中也是如此。当你得到成员时,Hibernate 魔法会填充它。这样你就永远不必暴露对象。也不要在潜在的代理对象上使用 instanceof。但无论如何,这是一种代码气味。

