Grails查询过滤关联并仅返回匹配的实体

时间:2012-08-21 15:35:49

标签: sql grails gorm

我有以下1 - M(单向)关系:

Customer (1) -> (M) Address

我正在尝试过滤包含特定文本的特定客户的地址,例如

def results = Customer.withCriteria {
    eq "id", 995L
    addresses {
        ilike 'description', '%text%'
    }
}

问题是这会返回客户,当我依次访问“地址”时,它会提供完整的地址列表,而不是过滤的地址列表。

由于无法从条件查询中访问关联表,因此我无法使用Address.withCriteria

我希望避免恢复原始SQL查询,因为这意味着无法使用大量功能来灵活且可重用地构建条件查询。

很想听到任何想法......

2 个答案:

答案 0 :(得分:1)

我相信2.1中不同行为的原因是here

具体来说:

  

以前默认的LEFT JOIN用于跨关联的条件查询现在是INNER JOIN。

IIRC,当您使用内部联接时,Hibernate不会急切地加载关联。

您似乎可以使用createAlias指定外部联接example here

我对这个特殊问题的体验来自于NHibernate的经验,所以我无法真正了解如何使它正常工作。如果结果不正确,我很乐意删除这个答案。

答案 1 :(得分:0)

试试这个:

def results = Customer.createCriteria().listDistinct() {
    eq('id', 995L)
    addresses {
        ilike('description', '%Z%')
    }
}

这为您提供了具有正确ID和任何匹配地址的Customer对象,并且只提供了匹配以外的地址。

您还可以使用此查询(稍加修改)来获取具有匹配地址的所有客户:

def results = Customer.createCriteria().listDistinct() {
    addresses {
        ilike('description', '%Z%')
    }
}

results.each {c->
    println "Customer " + c.name
    c.addresses.each {address->
        println "Address " + address.description
    }
}

修改 以下是域类和添加地址的方式:

class Customer {
  String name
  static hasMany = [addresses: PostalAddress]
  static constraints = {
  }
}
class PostalAddress {
  String description
  static belongsTo = [customer: Customer]
  static constraints = {
  }
}
//added via Bootstrap for testing
def init = { servletContext ->
    def custA = new Customer(name: 'A').save(failOnError: true)
    def custB = new Customer(name: 'B').save(failOnError: true)
    def custC = new Customer(name: 'C').save(failOnError: true)

    def add1 = new PostalAddress(description: 'Z1', customer: custA).save(failOnError: true)
    def add2 = new PostalAddress(description: 'Z2', customer: custA).save(failOnError: true)
    def add3 = new PostalAddress(description: 'Z3', customer: custA).save(failOnError: true)
    def add4 = new PostalAddress(description: 'W4', customer: custA).save(failOnError: true)
    def add5 = new PostalAddress(description: 'W5', customer: custA).save(failOnError: true)
    def add6 = new PostalAddress(description: 'W6', customer: custA).save(failOnError: true)

}

当我运行时,我得到以下输出:

Customer A
Address Z3
Address Z1
Address Z2