java Hibernate 急切加载(获取所有属性不起作用)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5703337/
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
Hibernate eager loading (fetch all properties does not work)
提问by vbence
Basically I want to eager-load properties. I have the following HQL query:
基本上我想急切加载属性。我有以下 HQL 查询:
SELECT u.id AS id, u.name AS text, u AS obj FROM User AS u fetch all properties
I would expect this to execute one query only. Instead I got N+1 queries.
我希望它只执行一个查询。相反,我收到了 N+1 个查询。
The code is the following:
代码如下:
Query q = mySession.createQuery(
"SELECT u.id AS id, u.name AS text, u AS obj FROM User AS u fetch all properties")
.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);
for (Iterator i = q.iterate(); i.hasNext();) {
Object line = i.next();
System.out.println(line);
}
The output I get (with hibernate.show_sql
set to true
) is:
我得到的输出(hibernate.show_sql
设置为true
)是:
Hibernate: select user0_.id as col_0_0_, user0_.name as col_1_0_, user0_.id as col_2_0_ from user user0_
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.location as location0_0_ from user user0_ where user0_.id=?
{id=1, obj=User@b6548 [id='1' name='John' ], text=John}
Hibernate: select user0_.id as id0_0_, user0_.name as name0_0_, user0_.location as location0_0_ from user user0_ where user0_.id=?
{id=2, obj=User@4865ce [id='2' name='Arnold' ], text=Arnold}
Ps: The situation is just the same without transformers.
Ps:没有变压器的情况也是一样。
Edit:
编辑:
The file with the entity-mappings:
带有实体映射的文件:
<hibernate-mapping>
<class name="User" table="user">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="location"/>
<map name="customPrices" table="custprice">
<key column="user"/>
<map-key-many-to-many column="product" class="Product"/>
<element column="price" type="double"/>
</map>
</class>
<class name="Product" table="product">
<id name="id" column="id">
<generator class="native"/>
</id>
<property name="name"/>
<property name="listprice"/>
</class>
</hibernate-mapping>
I tried adding lazy="false"
to the class and to the individual properties. No difference.
我尝试添加lazy="false"
到类和各个属性中。没有不同。
My configuration file:
我的配置文件:
<hibernate-configuration>
<session-factory>
<property name="connection.url">jdbc:mysql://192.168.0.203/hibtest</property>
<property name="connection.username">hibtest</property>
<property name="connection.password">hibb345</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
<property name="current_session_context_class">thread</property>
<property name="hibernate.show_sql">true</property>
<mapping resource="combined.hbm.xml" />
</session-factory>
</hibernate-configuration>
Edit2:
编辑2:
Even the following code causes N+1 query. Although I only fetch the ID field, which according to documentation should not cause objects to load.
即使是下面的代码也会导致 N+1 查询。虽然我只获取 ID 字段,但根据文档,它不会导致对象加载。
for (Iterator i = q.iterate(); i.hasNext();) {
Object line = i.next();
User u = (User)((Map)line).get("obj");
System.out.println(u.getId());
}
回答by vbence
The problem was with .iterate()
. According to Hibernate API docs:
问题出在.iterate()
. 根据Hibernate API 文档:
Entities returned as results are initialized on demand. The first SQL query returns identifiers only.
作为结果返回的实体按需初始化。第一个 SQL 查询仅返回标识符。
This is a special function to be used when we expect the resulting objects to be already cached. They will be (lazy) loaded when accessed.
当我们期望结果对象已经被缓存时,这是一个特殊的函数。它们将在访问时(延迟)加载。
So for general use, to get an iterator on a result of a query you should use .list().iterate()
.
因此,对于一般用途,要获取查询结果的迭代器,您应该使用.list().iterate()
.
Thanks for Eran Harelfor the help.
感谢Eran Harel的帮助。
回答by axtavt
In essense, the cause of your problem is an attempt to incorporate result transformation logic into a query.
从本质上讲,问题的原因是试图将结果转换逻辑合并到查询中。
I think it would be better to make a simple HQL query and then apply your specific result transformation logic in a custom ResultTransformer
, something like this:
我认为最好进行一个简单的 HQL 查询,然后在自定义中应用您的特定结果转换逻辑ResultTransformer
,如下所示:
Query q = mySession.createQuery("FROM User")
.setResultTransformer(new ResultTransformer() {
public List transformList(List l) { return l; }
public Object transformTuple(Object[] tuple, String[] aliases) {
Map<String, Object> r = new HashMap<String, Object>();
User u = (User) tuple[0];
r.put("obj", u);
r.put("id", u.getId());
r.put("text", u.getName());
return r;
}
});
回答by SPee
Looks like it cannot retrieve the obj in a single query with separate columns.
看起来它无法在具有单独列的单个查询中检索 obj。
Since you use the same values from User for the other columns, the example from @axtavt seems your best solution.
由于您对其他列使用来自 User 的相同值,因此来自 @axtavt 的示例似乎是您最好的解决方案。