我在Grails服务类中编写了条件查询,希望在该类中执行渴望的连接,并避免在将结果显示为JSON响应或GSP时延迟加载子对象。查询按预期执行(在DataSource.groovy中设置hibernate.show_sql = true可以看到查询),但是当我在GSP中抓取关联时,我可以看到Hibernate正在执行后续查询,就像延迟加载一样协会。我不相信这种急切的加载实际上是有效的。我不想在我的域类中为这些关联设置lazy:false。

这是条件查询:

def market = Market.withCriteria(uniqueResult:true){
    idEq(marketId)
    fetchMode 'resourceAssignments', FetchMode.JOIN
    fetchMode 'resourceAssignments.userRole', FetchMode.JOIN
    fetchMode 'resourceAssignments.userRole.role', FetchMode.JOIN
    fetchMode 'resourceAssignments.userRole.user', FetchMode.JOIN
    resourceAssignments{
        userRole{
            role{
                'in'('name', roleNames)
            }
        }
    }
}

上面的查询返回没有任何问题。但是,当我尝试在我的GSP中运行以下代码时,我可以看到Hibernate正在发出第二个查询,就像它在懒惰地获取resourceAssignments一样:
<g:each in="${market.resourceAssignments}" var="ra">
</g:each>

我什至尝试通过创建一个空的WebRequestInterceptor并在resources.groovy中将openSessionInViewInterceptor设置为使用它来使用No-Op拦截器覆盖OpenSessionInViewInterceptor。完成该操作后,我得到一个org.hibernate.LazyInitializationException似乎可以验证我的想法-即使我指定要热切获取这些关联,Hibernate或GORM仍在尝试执行第二个查询。

最佳答案

它似乎是带有条件查询的Grails错误。这是一个有效的HQL查询:

def market = Market.executeQuery(
    'select m from Market m ' +
    'inner join fetch m.resourceAssignments as ra ' +
    'inner join fetch ra.userRole as ur ' +
    'inner join fetch ur.role as role ' +
    'inner join fetch ur.user as user ' +
    'where m.id=:marketId and role.name in (:roleNames)',
    [marketId: marketId, roleNames: roleNames], [max: 1])[0]

08-04 03:20
查看更多