Ale*_*lex 3 grails associations h2 grails-orm
在下面的例子中,我希望Product.searchAll能够匹配添加剂和产品,但它似乎忽略了eq('name', taste)
.
class Additive {
String flavor
static belongsTo = [product:Product]
}
class Product {
String name
static hasMany = [additives:Additive]
static constraints = {
name nullable:true
}
static namedQueries = {
searchAll { taste ->
or {
eq('name', taste)
additives { eq('flavor', taste) }
}
}
searchAdditives { taste ->
additives { eq('flavor', taste) }
}
searchProducts { taste ->
eq('name', taste)
}
}
}
class SearchSpec extends grails.plugin.spock.IntegrationSpec {
def choc, muff
def 'searchAll should return products and additives that match - THIS FAILS'() {
setup:
createTestProducts()
expect:
Product.searchAll("chocolate").list() == [choc, muff]
}
def 'searchProducts should return only products that match - THIS PASSES'() {
setup:
createTestProducts()
expect:
Product.searchProducts("chocolate").list() == [choc]
}
def 'searchAdditives should return only additives that match - THIS PASSES'() {
setup:
createTestProducts()
expect:
Product.searchAdditives("chocolate").list() == [muff]
}
private def createTestProducts() {
// create chocolate
choc = new Product(name:'chocolate').save(failOnError:true, flush:true)
// create a chocoloate-flavored muffin
muff = new Product(name:'muffin').addToAdditives(flavor:'chocolate').save(failOnError:true, flush:true)
}
}
Run Code Online (Sandbox Code Playgroud)
生成的SQL如下:
select this_.id as id1_1_, this_.version as version1_1_,
this_.name as name1_1_, additives_1_.id as id0_0_,
additives_1_.version as version0_0_, additives_1_.flavor as
flavor0_0_, additives_1_.product_id as product4_0_0_ from product
this_ inner join additive additives_1_ on
this_.id=additives_1_.product_id where (this_.name=? or
(additives_1_.flavor=?))
Run Code Online (Sandbox Code Playgroud)
我的语法有问题,或者这是Grails,GORM还是H2的问题?
我的猜测,快速查看您的查询,是Grails/GORM正在执行inner join
.如果表之间存在关系,则内部联接仅匹配.在上面的示例中,该查询永远不会匹配choc
,因为choc
没有任何关联的添加剂.
所以,这不是or
失败的,而是实际的查询.启动localhost:8080/{yourapp}/dbConsole并运行相同的查询,但没有where
语句.你应该看到你只得到含有一种或多种添加剂的产品.
我相信(未经测试)你可以强制LEFT JOIN
使用这样的语法:
import org.hibernate.criterion.CriteriaSpecification
...
searchAll { taste ->
createAlias("additives", "adds", CriteriaSpecification.LEFT_JOIN)
or {
eq('name', taste)
eq('adds.flavor', taste)
}
}
Run Code Online (Sandbox Code Playgroud)
这应该强制左(或外)连接,允许产品没有匹配的添加剂.注意:使用外连接时可能会出现重复结果,但这取决于您的特定使用方案.
归档时间: |
|
查看次数: |
2082 次 |
最近记录: |