Grails中的Where 查詢

 where 方法,Grails 2.0被引入,構建在 Detached Criteria 之上,爲普通查詢提供了一個增強的運行時檢查的查詢DSLwhere 方法比動態查詢更靈活,比criteria的代碼更簡潔而且爲撰寫查詢提供了一個強大的機制。

基本查詢

 where 方法接受一個閉包看起來非常類似於Groovy的規範集合方法。閉包用規範的Groovy語法定義一個邏輯條件。例如:

def query = Person.where {

   firstName == "Bart"

}

Person bart = query.find()

返回的對象是一個 DetachedCriteria 實例,這意味着他不語任何特定的數據庫連接或會話相關聯。意味着你可以使用 where在類層面去定義普通查詢:

class Person {

    static simpsons = where {

         lastName == "Simpson"

    }

    …

}

Person.simpsons.each {

    println it.firstname

}

查詢執行是懶加載,僅僅在使用 DetachedCriteria實例之後才發生。如果你要執行一個立即生效的where樣式的查詢,可以改用 findAll  find方法的來完成:

def results = Person.findAll {

     lastName == "Simpson"

}

def results = Person.findAll(sort:"firstName") {

     lastName == "Simpson"

}

Person p = Person.find { firstName =="Bart" }

每一個Groovy操作映射到一個常規的criteria方法。下表提供了一個Groovy操作映射方法的列示:

 

Operator

Criteria Method

Description

==

eq

Equal to

!=

ne

Not equal to

> 

gt

Greater than

< 

lt

Less than

>=

ge

Greater than or equal to

<=

le

Less than or equal to

in

inList

Contained within the given list

==~

like

Like a given string

=~

ilike

Case insensitive like

這使我們利用規範的Groovy比較操作符和邏輯來定製複雜的查詢成爲可能:

def query = Person.where {

    (lastName != "Simpson" &&firstName !="Fred") || (firstName =="Bart" && age > 9)

}

def results = query.list(sort:"firstName")

Groovy的正則表達式匹配操作符映射到likeilike查詢。除非在表達式的右邊是一個  Pattern 對象,這種情況下,他們映射到一個 rlike 查詢:

def query = Person.where {

     firstName ==~ ~/B.+/

}

注意,只有底層數據庫支持正則表達式, rlike 查詢纔會被支持。

一個 between 條件查詢可以使用 in 關鍵詞來組合一個。

def query = Person.where {

     age in 18..65

}

最後,你可以用null和標準的比較運算符來做 isNull isNotNull 樣式查詢:

def query = Person.where {

     middleName == null

}

查詢組合

由於 where方法的返回值是一個 DetachedCriteria實例,你可以從原來的查詢組合成新的查詢:

def query = Person.where {

     lastName == "Simpson"

}

def bartQuery = query.where {

     firstName == "Bart"

}

Person p = bartQuery.find()

注意,你不能在where方法閉包中定義變量傳遞,除非他已經明確地被轉換成了 DetachedCriteria 實例。也就是說下面的語句是錯誤的:

def callable = {

    lastName == "Simpson"

}

def query = Person.where(callable)

上面的代碼必須這樣寫:

import grails.gorm.DetachedCriteria

def callable = {

    lastName == "Simpson"

} as DetachedCriteria<Person>

def query = Person.where(callable)

這如你所看到的,閉包定義是轉換到 (使用Groovy as 關鍵字)一個在Person類中標記的 DetachedCriteria實例。

關聯、分離和取反

就像前面提到的,你可以組合Groovy標準的邏輯運算符 (||  &&),形成關聯和分離:

def query = Person.where {

    (lastName != "Simpson" &&firstName !="Fred") || (firstName =="Bart" && age > 9)

}

你還可以使用邏輯比較符!進行取反。

def query = Person.where {

    firstName == "Fred" &&!(lastName == 'Simpson')

}

屬性比較查詢

如果你在表達式的兩邊都是用屬性名,那麼相應的屬性比較條件會被自動使用:

def query = Person.where {

   firstName == lastName

}

下表描述了每個比較操作映射到每個條件屬性比較法:

Operator

Criteria Method

Description

==

eqProperty

Equal to

!=

neProperty

Not equal to

> 

gtProperty

Greater than

< 

ltProperty

Less than

>=

geProperty

Greater than or equal to

<=

leProperty

Less than or equal to

查詢關聯

關聯可以被查詢,使用點操作符來指定關聯查詢的屬性名:

def query = Pet.where {

    owner.firstName == "Joe" ||owner.firstName =="Fred"

}

你可以將一組條件放進一個閉包方法中進行調用,在哪裏,方法名匹配關聯名:

def query = Person.where {

    pets { name == "Jack" || name == "Joe" }

}

這個技術可以結合其他頂層規範:

def query = Person.where {

     pets { name == "Jack" } || firstName=="Ed"

}

集合關聯還可以用來查詢集合的大小:

def query = Person.where {

       pets.size() == 2

}

下表顯示了查詢集合大小的標準比較運算符:

Operator

Criteria Method

Description

==

sizeEq

The collection size is equal to

!=

sizeNe

The collection size is not equal to

> 

sizeGt

The collection size is greater than

< 

sizeLt

The collection size is less than

>=

sizeGe

The collection size is greater than or equal to

<=

sizeLe

The collection size is less than or equal to

子查詢

可能會在where查詢中使用子查詢。例如,找出所有年齡大於平均年齡的人:

final query = Person.where {

  age > avg(age)

}

下面是相關子查詢的列表:

Method

Description

avg

The average of all values

sum

The sum of all values

max

The maximum value

min

The minimum value

count

The count of all values

property

Retrieves a property of the resulting entities

你可以使用of 方法申請添加條件到任何子查詢,通過一個閉包來傳遞條件:

def query = Person.where {

  age > avg(age).of { lastName =="Simpson" } &&firstName =="Homer"

}

因爲屬性子查詢返回多個結果,可以使用比較結果作爲條件。例如,下面的例子查詢一個比“simpson”年齡小的人。

Person.where {

    age < property(age).of {lastName =="Simpson" }

}

其他函數

有幾個函數可以加入到你的查詢內容中。列示如下:

Method

Description

second

The second of a date property

minute

The minute of a date property

hour

The hour of a date property

day

The day of the month of a date property

month

The month of a date property

year

The year of a date property

lower

Converts a string property to upper case

upper

Converts a string property to lower case

length

The length of a string property

trim

Trims a string property

目前函數只能應用於領域類的屬性和關聯,你不能在諸如子查詢的結果中使用函數。

例如,下面的查詢尋找所有在2011年出生的人:

def query = Pet.where {

    year(birthDate) == 2011

}

你還可以在關聯中應用函數:

def query = Person.where {

    year(pets.birthDate) == 2009

}

批量更新和刪除

由於每一個 where 方法調用返回一個 DetachedCriteria 實例,你可以使用 where 查詢執行批量操作。例如,批量更新和刪除。

例如,下面的查詢將所有 lastName"Simpson"的人的lastName更新爲"Bloggs"

def query = Person.where {

    lastName == 'Simpson'

}

inttotal = query.updateAll(lastName:"Bloggs")

注意,一個批量操作方面的限制是連接查詢(查詢查詢關聯)是不允許的。

批量刪除記錄你可以使用deleteAll 方法:

def query = Person.where {

    lastName == 'Simpson'

}

inttotal = query.deleteAll()

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章