Grails 准则使用「;“内部连接”;取而代之的是;“左连接”;默认情况下,使我的查询不是按我计划的方式工作
问题是:在这个特定示例中,如何使GORM生成左连接而不是内部连接 试验台: 给定A类、B类和C类:Grails 准则使用「;“内部连接”;取而代之的是;“左连接”;默认情况下,使我的查询不是按我计划的方式工作,grails,gorm,Grails,Gorm,问题是:在这个特定示例中,如何使GORM生成左连接而不是内部连接 试验台: 给定A类、B类和C类: class A{ B someObject } class B{ C importantObject } class C{ boolean interestingFlag } 我想列出一个类的所有元素: 他们的B.C对象为null或 他们的B.C对象兴趣标志值为false 到目前为止,我尝试的是: 此方法生成正确的列表,其中B.C为null(条件2已注释掉)或正确
class A{
B someObject
}
class B{
C importantObject
}
class C{
boolean interestingFlag
}
我想列出一个类的所有元素:
- 他们的B.C对象为null或
- 他们的B.C对象兴趣标志值为false
Hibernate: select this_.id as id1_2_, this_.version as version1_2_,
this_.some_object_id as some3_1_2_, someobject1_.id as id2_0_,
someobject1_.version as version2_0_, someobject1_.important_object_id as
important3_2_0_, importanto2_.id as id0_1_, importanto2_.version as version0_1_,
importanto2_.interesting_flag as interest3_0_1_ from a this_
inner join b someobject1_ on this_.some_object_id=someobject1_.id
inner join c importanto2_ on someobject1_.important_object_id=importanto2_.id
where ((someobject1_.important_object_id is null or (importanto2_.interesting_flag=?)))
当我直接将其复制并粘贴到pgAdmin查询工具中,并更改了一些内容(内部连接更改为左连接,并提供了interestingFlag=“false”参数)时,一切都按照我的要求工作(我得到了a.B.C=null和a.B.C.importantFlag=false对象)
使用left join来实现这一点。这应该行得通,但我还没有现场测试过
def result = A.withCriteria{
someObject {
createAlias("importantObject", "io", CriteriaSpecification.LEFT_JOIN)
or{
isNull('importantObject') // conditional 1
eq('io.interestingFlag', false) // conditional 2
}
}
}
艾德:基于这篇文章:这也应该有效:
def result = A.withCriteria{
someObject {
isNull('importantObject') // conditional 1
importantObject(JoinType.LEFT) {
eq('interestingFlag', false) // conditional 2
}
}
}
请在两种解决方案上发布您的结果
编辑2:这是一个与您描述的情况完全相同的查询,但与您的示例不同。您必须从这里开始,使用showSql调试生成的sql并处理左连接
def result = A.withCriteria{
or {
isNull('someObject')
eq('someObject.importantObject.interestingFlag', false)
}
}
测试和工作解决方案:
def result = A.withCriteria{
createAlias('someObject', 'so', CriteriaSpecification.LEFT_JOIN)
createAlias('so.importantObject', 'imp', CriteriaSpecification.LEFT_JOIN)
or {
isNull('so.importantObject')
eq('imp.interestingFlag', false)
}
}
意见中建议的解决方案更新:
def result = A.withCriteria{
createAlias('someObject', 'so', JoinType.LEFT_OUTER_JOIN)
createAlias('so.importantObject', 'imp', JoinType.LEFT_OUTER_JOIN)
or {
isNull('so.importantObject')
eq('imp.interestingFlag', false)
}
}
我只能通过HQL实现左外连接
Class Transaction {
String someProperty
static hasMany = [reviews: Review]
static hasOne = [reviewQueue: ReviewQueue]
}
Class ReviewQueue {
Transaction transaction
Boolean isComplete
Boolean isReady
}
Class Review {
Transaction transaction
String reviewResult
}
def list = Transaction.executeQuery(
"select t.id, rq.isReady, rq.isComplete, count(r.transaction.id) " +
"from Transaction t " +
"join t.reviewQueue rq " +
"left outer join t.reviews r " +
"where rq.isComplete = false " +
"and rq.isReady = true " +
"group by t.id " +
"having count(r.transaction.id) = 0 " +
"order by rq.transaction.id ",
[max: 10, offset: 0])
尝试在数据源中启用logSql=true,并查看此qquery生成的sql。请在这里发布。@TomaszKalkosiński根据请求,这里是hibernate sql输出。我知道如何调整查询以使其按我所希望的方式工作。我不知道如何让GORM生成正确的查询它们都生成了错误。解决方案1:Class org.hibernate.QueryException Message无法解析属性:importantObject of:A。解决方案2:groovy.lang.MissingMethodException Message没有方法签名:AController.importantObject()适用于参数类型:(javax.persistence.criteria.JoinType,AController$\u list\u closure1\u closure2\u closure3)值:[左,a控制器$\u列表\u关闭1\u关闭2_closure3@40230d]这很奇怪,因为消息指示对象上的错误,而importantObject位于someObject闭包中。至于解决方案1,尝试在某个对象上创建alias,看看这是否有帮助。将alias更改为createAlias(“someObject.ImportantoObject”、“io”、CriteriaSpecification.LEFT_JOIN”)后运气不佳。现在它找不到“io()method”@AndrzejBobak,我认为你的问题有问题,它也会影响你的查询。您提出的结构与您的问题和查询不匹配。如果没有正确的结构,我们无法继续前进,这样我们就可以修复您的查询。这是我的示例项目中的内容的精确副本。为了回答这个问题而设置它并生成sql输出花了我大约10分钟的时间。我使用Grails2.2.1和Postgresql 8.3。如果你感兴趣,我可以给你一份这个项目的副本,但它太小了,可以在几分钟内创建(3个类,每个类有1个字段,生成的视图+支架)。我真的不明白你所说的“我提出的结构与我的问题和疑问不符”是什么意思。先生,你是个救命恩人!!CriteriaSpecification.LEFT_联接已被弃用。对于最新版本,请使用JoinType.LEFT\u OUTER\u JOIN。资料来源:
def result = A.withCriteria{
createAlias('someObject', 'so', JoinType.LEFT_OUTER_JOIN)
createAlias('so.importantObject', 'imp', JoinType.LEFT_OUTER_JOIN)
or {
isNull('so.importantObject')
eq('imp.interestingFlag', false)
}
}
Class Transaction {
String someProperty
static hasMany = [reviews: Review]
static hasOne = [reviewQueue: ReviewQueue]
}
Class ReviewQueue {
Transaction transaction
Boolean isComplete
Boolean isReady
}
Class Review {
Transaction transaction
String reviewResult
}
def list = Transaction.executeQuery(
"select t.id, rq.isReady, rq.isComplete, count(r.transaction.id) " +
"from Transaction t " +
"join t.reviewQueue rq " +
"left outer join t.reviews r " +
"where rq.isComplete = false " +
"and rq.isReady = true " +
"group by t.id " +
"having count(r.transaction.id) = 0 " +
"order by rq.transaction.id ",
[max: 10, offset: 0])