Grails 2.4.4 完全忽略 fetch:'join' *使用 PostgreSQL 时*
Grails 2.4.4 completely ignores fetch:'join' *when using PostgreSQL*
更新:这似乎只在使用 PostgreSQL 时发生。我在这里提交了一个项目:https://github.com/jbwiv/testfetch 有两个分支。 "master" 使用 h2,"postgres" 使用 PostgreSQL。
尝试每个分支,然后转到 localhost:8080/testfetch/console。
在该控制台中,键入:
import testfetch.Employee
import testfetch.User
Employee.list()
在 H2 中,我得到了我期望的结果:
hibernate.SQL select this_.id as id1_1_1_, this_.version as version2_1_1_, user2_.id as id1_0_0_, user2_.version as version2_0_0_, user2_.employee_id as employee3_0_0_ from employee this_ left outer join app_user user2_ on this_.id=user2_.employee_id
然而,在 postgres 分支中,我得到:
hibernate.SQL /* criteria query */ select this_.id as id1_1_0_, this_.version as version2_1_0_ from employee this_
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
这对我们来说是一个巨大的障碍。非常感谢您提供的任何反馈。
我在 Grails 2.4.4 和 Hibernate4 中实时获得惰性行为以正常工作。
比如我有两个类,Employee和User。
class Employee {
User user
static mapping = {
user fetch:'join'
}
static belongsTo = User
}
class User {
Employee employee
static mapping = {
employee fetch:'join'
table 'app_user'
}
}
但是,当我尝试使用此设置查询这些对象时,我仍然遇到 N+1 问题。例如
Employee.list()
Employee.executeQuery("select e from Employee e")
所有 导致对员工 table 的一次查询,其中 returns 21 名员工,然后对 app_user table(用户被映射到)。
然而,
Employee.withCriteria {fetchMode 'user', FetchMode.JOIN)
有效。在这种情况下,我只执行了一个查询。
我做错了什么?
蒂亚
zyro 在 JIRA 问题中正确指出我们的 PostgreSQL 配置中有 "max_fetch_depth = 0"。
引用他的话:
postgres 分支有 dataSource.hibernate.max_fetch_depth = 0 并且 hibernate 文档说 A 0 禁用默认的外部连接获取。这可能是原因吗?
的确,在删除它之后,它以预期的方式执行。
更新:这似乎只在使用 PostgreSQL 时发生。我在这里提交了一个项目:https://github.com/jbwiv/testfetch 有两个分支。 "master" 使用 h2,"postgres" 使用 PostgreSQL。
尝试每个分支,然后转到 localhost:8080/testfetch/console。
在该控制台中,键入:
import testfetch.Employee
import testfetch.User
Employee.list()
在 H2 中,我得到了我期望的结果:
hibernate.SQL select this_.id as id1_1_1_, this_.version as version2_1_1_, user2_.id as id1_0_0_, user2_.version as version2_0_0_, user2_.employee_id as employee3_0_0_ from employee this_ left outer join app_user user2_ on this_.id=user2_.employee_id
然而,在 postgres 分支中,我得到:
hibernate.SQL /* criteria query */ select this_.id as id1_1_0_, this_.version as version2_1_0_ from employee this_
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
hibernate.SQL /* load testfetch.User */ select user0_.id as id1_0_0_, user0_.version as version2_0_0_, user0_.employee_id as employee3_0_0_ from app_user user0_ where user0_.employee_id=?
这对我们来说是一个巨大的障碍。非常感谢您提供的任何反馈。
我在 Grails 2.4.4 和 Hibernate4 中实时获得惰性行为以正常工作。
比如我有两个类,Employee和User。
class Employee {
User user
static mapping = {
user fetch:'join'
}
static belongsTo = User
}
class User {
Employee employee
static mapping = {
employee fetch:'join'
table 'app_user'
}
}
但是,当我尝试使用此设置查询这些对象时,我仍然遇到 N+1 问题。例如
Employee.list()
Employee.executeQuery("select e from Employee e")
所有 导致对员工 table 的一次查询,其中 returns 21 名员工,然后对 app_user table(用户被映射到)。
然而,
Employee.withCriteria {fetchMode 'user', FetchMode.JOIN)
有效。在这种情况下,我只执行了一个查询。
我做错了什么?
蒂亚
zyro 在 JIRA 问题中正确指出我们的 PostgreSQL 配置中有 "max_fetch_depth = 0"。
引用他的话:
postgres 分支有 dataSource.hibernate.max_fetch_depth = 0 并且 hibernate 文档说 A 0 禁用默认的外部连接获取。这可能是原因吗?
的确,在删除它之后,它以预期的方式执行。