看似随机1 = 1由GORM生成的where子句在哪里关闭

时间:2017-04-10 19:36:03

标签: hibernate grails gorm

问题示例程序:https://github.com/HybridProgrammer/GormOneIsOneError

有问题的GORM代码

def query = UserData.where {
        (
                teams { id in me.getAuthorities().id } && status { isOpen == true }
        ) || (
                owner == me && status { isOpen == true }
        )
    }

问题摘要

当我希望在(?)

中看到teams_alia1_.id时,生成的SQL查询偶尔会产生一个包含1 = 1的where子句

问题的详细描述

我写了两个集成测试来说明这个问题:

请参阅src / intrgration-test / groovy / ExampleITSpec.groovy

整合测试1

void "never fails - direct approach"() {
    given:
    setupData()
    def me = User.first()

    when:
    def query = UserData.where {
        (
                teams { id in me.getAuthorities().id } && status { isOpen == true }
        ) || (
                owner == me && status { isOpen == true }
        )
    }

    then:
    me.getAuthorities().size() == 1
    query.size() == 2
}

始终生成SQL

select count(*) as y0_ 
from user_data this_ inner join status status_ali2_ 
     on this_.status_id=status_ali2_.id 
     inner join workflow_role_teams teams5_ 
     on this_.id=teams5_.user_data_teams_id 
     inner join role teams_alia1_ 
     on teams5_.role_id=teams_alia1_.id 
where 
(((teams_alia1_.id in (?)) and (status_ali2_.is_open=?)) 
or 
(this_.owner_id=? and (status_ali2_.is_open=?))) limit ?

集成测试2

void "sometimes fails"() {
    given:
    setupData()
    def me = User.first()

    when:
    def query = exampleService.getMyOrMyTeamsData(me)

    then:
    me.getAuthorities().size() == 1
    query.size() == 2
}

偶尔会生成SQL

select count(*) as y0_ 
from user_data this_ inner join status status_ali2_ 
    on this_.status_id=status_ali2_.id 
    inner join workflow_role_teams teams5_ 
    on this_.id=teams5_.user_data_teams_id 
    inner join role teams_alia1_ 
    on teams5_.role_id=teams_alia1_.id 
where 
((1=1 and (status_ali2_.is_open=?)) 
or 
(this_.owner_id=? and (status_ali2_.is_open=?))) limit ?

1 = 1来自哪里?

ExampleService

def getMyOrMyTeamsData(User me) {
    // To fix the test Toggle these two lines
    def user = me
//        def user = User.get(me.id)

    def query = UserData.where {
        (
                teams { id in me.getAuthorities().id } && status { isOpen == true }
        ) || (
                owner == user && status { isOpen == true }
        )
    }

    return query

}

更新1

在调试应用程序时,您可以清楚地看到 authority 变量在工作版本中传递给DetachedCriteria#handleJunction(Closure callable),但在从服务方法调用时消失。

集成测试1 - 具有权限属性

Integration Test 1 - Has authorities attribute

集成测试2 - 无权限属性

Integration Test 2 - No authorities attribute

解决方案

请参阅解决方案分支 https://github.com/HybridProgrammer/GormOneIsOneError/commit/8c3d77f82081d0367961345b4fc70c789e322318

1 个答案:

答案 0 :(得分:1)

对我来说,测试总是失败,我不知道为什么测试2和3显示不同的行为,但在UserData.groovy中将List teams更改为List<Role> teams后,测试3通过了。

在GORM文档中,通常会省略映射字段的声明,在这种情况下也适用。

希望这也适合你。