list - 具有一对多关系的GORM createCriteria

标签 list grails gorm one-to-many createcriteria

几个小时以来,我试图弄清楚如何使用一种必须在列表中的条件来创建条件。

如果减少代码,则有以下两个域类:

酒店-我要检索的基本域类:

class Hotel {

    static hasMany = [rooms: Room, amenities: HotelAmenity]

}

HotelAmenity -酒店拥有一系列设施。
class HotelAmenity {

    String name

}

#1 我的第一种方法是这样的:
PagedResultList pgl = Hotel.createCriteria().list(max: limit, offset: offset) {
    // ..
    and {
        amenities {
            'in'("id",myLongIdsList)
    }
}

这有效。但是在这种情况下,我得到的所有返回的酒店至少都包含和指定的场址中的至少。但是我的理想目标是检索仅具有所有指定的设施的酒店。

#2 所以我尝试了以下
// ..
amenities {
    condition.hotelAmenities.collect { it.toLong() }.each {
        and {
            eq('id', it)
        }
}

但是这段代码看起来像是弄乱​​了结果集,因为如果定义了多个功能,它总是返回一个空列表。
顺便说一句,在这种单人便利的情况下,我的结果列表中包含的所有酒店的便利设施列表中都没有其他便利设施,但我搜索的是这家酒店-即使分配了很多。我完全不了解这种行为。

#3 我尝试的另一种方法是使用listDistinct代替list。但是,一旦我认识到我没有PagedResultList,但返回了hotel domain objects列表,就没有再尝试此操作了。因此,我将没有totalCount参数(我需要使用它的分页功能)

因此,我被困在编写自己的查询和/或使用GORM方法解决此问题之间。也可能是我对有点困惑,应该对到底应如何工作。

对于任何通知或解决方案,我将非常高兴。

谢谢,
克里斯托弗

PS:我使用Grails版本1.3.7

PPS:如果缺少任何信息,请告诉我。

编辑

现在这是我附带的解决方案:
Map sqlParams = [:]
String mySql = "SELECT SQL_CALC_FOUND_ROWS hotel.id FROM hotel WHERE "
if(hotelAmenities.size()>0) {
  String commaSeperatedAmenities = hotelAmenities.toString()
  // the amenity IDs as comma seperates list so we can use them in the `IN` statement (ie 1,3,6,7)
  commaSeperatedAmenities = commaSeperatedAmenities.substring(1,commaSeperatedAmenities.length()-1)
  mySql += '( SELECT COUNT(hotel_amenities_id) from hotel_hotel_amenity ' +
           'WHERE hotel_amenities_id = hotel.id AND hotel_amenity_id IN ' +
           '(' + comaAmentities + ') ) = ' + condition.hotelAmenities.size()
}

mySql += 'LIMIT :offset, :limit'
sqlParams.put("offset",offset)
sqlParams.put("limit",limit)

def mresult = sqlInstance.rows(mySql,sqlParams)
List<Hotel> hotels = Hotel.getAll(mresult.collect {it.id})
int calcFoundRows = sqlInstance.rows("SELECT FOUND_ROWS()").get(0).get("FOUND_ROWS()").toString().toInteger()

最佳答案

动态建立标准:

def neededAmenities = ...

PagedResultList pgl = Hotel.createCriteria().list(max: limit, offset: offset) {
    // ..
    amenities {
        and {
            neededAmenities.each { needed ->
                idEq (needed.id)
            }
        }
    }
}

在纯SQL中,这并不容易:
where exists(amenities.id == XXX) and exists(amenities.id == YYY) and (...) ... 

您可以使用以下语义的intersect查询进行更优化:
where intersect(
    select id from amenities where ..., 
    (:neededAmenities)) 
= (:neededAmenities)

一些示例here

编辑:我试图构造第二类条件,但失败了-I see no way to build having count -type condition。无论如何,它将比几个in -s慢,因为所有count都必须Amenities hotels

关于list - 具有一对多关系的GORM createCriteria,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7144944/

相关文章:

grails - 为什么会出现 “No owner defined between domain classes..”错误?

python - 如何在列表中的每个元素前面添加新值?

c# - 如何根据自己的属性和另一个列表的属性对列表进行排序?

rest - 注销api错误-Grails中的Rest Spring Security插件

序列化 Groovy 映射到 JS 文字对象的 Javascript 解析

grails - 如何只读取文件夹中的图像?

python - 更新元组中的列表

python - 计算嵌套列表中的所有元组元素

hibernate - Grails将Java 8域对象的LocalDateTime映射到Gorm

mongodb - 动态域模型属性未加载