使用Grails避免HQL中的子查询

时间:2012-05-13 19:57:31

标签: grails hql gorm

我有两个对象,房间类型和预订。简化它们是:

class Room {
  String description
  int quantity
}

class Reservation {
  String who
  Room room
}

我想查询所有房间以及每种类型的可用房间数量。在SQL中,这就是我想要的:

select id, quantity, occupied, quantity-coalesce(occupied, 0) as available
from room left join(select room_id, count(room_id) as occupied from reservation) 
on id = room_id;

我没有在任何地方尝试使用HQL来解决这个问题。

我很感激任何指针,因为我似乎在HQL或GORM中缺少一些相当基本的东西。

2 个答案:

答案 0 :(得分:1)

此处的问题是您尝试表示不属于您的域类的字段,例如availableoccupied。试图让HQL \ GORM执行此操作可能有点令人沮丧,但并非不可能。我想你在这里有几个选择......

1。)构建您的域类,以便更容易使用。也许您的房间需要通过映射表了解它的预订,或者或许写下您想要的代码看起来然后调整设计。

例如。也许你希望你的代码看起来像这样......

RoomReservation.queryAllByRoomAndDateBetween(room, arrivalDate, departureDate);  

然后你会像这样实现它......

    class RoomReservation{
        ...
        def queryAllByRoomAndDateBetween(def room, Date arrivalDate, Date departureDate){
           return RoomReservation.withCriteria {
             eq('room', room)
             and {
               between('departureDate', arrivalDate, departureDate)
             }
        }
    }

2。)我的第二个想法是...... 可以将数据库用于的好处。有时在代码中使用sql只是最有效的方法。 只是适度进行并保持集中和单元测试。我不建议您使用此方法,因为您查询并不复杂,但它是一个选项。我使用存储过程来查找“仪表板视图”,查询数百万个对象的摘要数据。

class Room{
    ...
  def queryReservations(){
      def sql = new Sql(dataSoruce);
      return sql.call("{call GetReservations(?)}", [this.id]) //<-- stored procedure.
  }
}

答案 1 :(得分:0)

我不确定如何用HQL中的子查询描述左连接。在任何情况下,如果HQL表达不够,你也可以轻松地在grails中执行原始SQL:

在您的服务中,注入dataSource并创建一个groovy.sql.Sql实例

def dataSource

[...]    

def sql= new Sql(dataSource)
sql.eachRow("...."){row->
    [...]
}

我知道,当你提出问题时,当人们试图光顾你的思维方式而不是回答你的问题或只是闭嘴时,我觉得非常讨厌,但在我看来,这个查询非常复杂,我会创建一个在我的数据结构中这个数字的概念,也许是与房间相关联的可用性表,它不仅可以计算数量,还可以计算占用值。

这不是每次需要时计算它。

只要我的$ .02如果它让你烦恼就忽略它。