Hibernate 预加载(获取所有属性不起作用)
基本上我想立即加载属性。我有以下 HQL 查询:
SELECT u.id AS id, u.name AS text, u AS obj FROM User AS u fetch all properties
我希望它只执行一个查询。相反,我收到了 N+1 个查询。
代码如下:
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);
}
我得到的输出(将 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:没有变压器时情况是一样的嗯>。
编辑:
带有实体映射的文件:
<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>
我尝试将 lazy="false"
添加到类和各个属性中。没有区别。
我的配置文件:
<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:
即使下面的代码也会导致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());
}
Basically I want to eager-load properties. I have the following HQL query:
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.
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: 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.
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.
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:
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.
for (Iterator i = q.iterate(); i.hasNext();) {
Object line = i.next();
User u = (User)((Map)line).get("obj");
System.out.println(u.getId());
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
问题出在
.iterate()
上。根据 Hibernate API 文档< /a>:这是一个特殊函数,当我们期望结果对象已经缓存时使用。它们在访问时将被(延迟)加载。
因此,对于一般用途,要获取查询结果的迭代器,您应该使用
.list().iterate()
。感谢 Eran Harel 的帮助。
The problem was with
.iterate()
. According to Hibernate API docs: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()
.Thanks for Eran Harel for the help.
从本质上讲,问题的原因是尝试将结果转换逻辑合并到查询中。
我认为最好做一个简单的 HQL 查询,然后在自定义 ResultTransformer 中应用特定的结果转换逻辑,如下所示:
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:看起来它无法在具有单独列的单个查询中检索 obj。
由于您对其他列使用来自 User 的相同值,因此 @axtavt 中的示例似乎是您的最佳解决方案。
Looks like it cannot retrieve the obj in a single query with separate columns.
Since you use the same values from User for the other columns, the example from @axtavt seems your best solution.