1、Criteria(条件查询)
Criteria可以通过createCriteria 或者 withCriteria 方法来使用
1 def user = User.findByUserId(params.user) 2 def entries = Post.createCriteria().list { 3 and { 4 eq('user', user) 5 between('created', new Date()-1, new Date()) 6 tags { 7 eq('name', 'Grails') 8 } 9 } 10 maxResults(10) 11 order("created", "desc") 12 }
and:里面所有查询条件都是“与”关系(全部为真)
tags:Tag对象
maxResults:记录数
order:排序
1 def entries = Post.withCriteria { 2 and { 3 eq('user', user) 4 between('created', new Date()-1, new Date()) 5 } 6 }
在系统中增加一个高级查询功能,用多条件组合查询Profile
新建一个闭包com.grailsinaction.UserController/advResults
1 def advSearch = { 2 } 3 4 def advResults = { 5 def profileProps = Profile.metaClass.properties*.name 6 def profiles = Profile.withCriteria { 7 "${params.queryType}" { 8 params.each { field, value -> 9 if (profileProps.grep(field) && value) { 10 ilike(field, value) 11 } 12 } 13 } 14 } 15 [ profiles : profiles ] 16 }
新建一个查询页面views/user/advSearch.gsp
1 <html> 2 <head> 3 <title>Advanced Search</title> 4 <meta name="layout" content="main"/> 5 </head> 6 7 <body> 8 <formset> 9 <legend>Advanced Search for Friends</legend> 10 <table> 11 <g:form action="advResults"> 12 <tr> 13 <td>Name</td> 14 <td><g:textField name="fullName" /></td> 15 </tr> 16 <tr> 17 <td>Email</td> 18 <td><g:textField name="email" /></td> 19 </tr> 20 <tr> 21 <td>Homepage</td> 22 <td><g:textField name="homepage" /></td> 23 </tr> 24 <tr> 25 <td>Query Type:</td> 26 <td> 27 <g:radioGroup name="queryType" labels="['And','Or','Not']" values="['and','or','not']" value="and" >${it.radio} ${it.label}</g:radioGroup> 28 </td> 29 </tr> 30 <tr> 31 <td/> 32 <td><g:submitButton name="search" value="Search"/></td> 33 </tr> 34 </g:form> 35 </table> 36 </formset> 37 </body> 38 </html>
新建一个查询结果返回页面views/user/advResults
1 <html> 2 <head> 3 <title>Advanced Search Results</title> 4 <meta name="layout" content="main"/> 5 </head> 6 7 <body> 8 <h1>Advanced Results</h1> 9 <p>Searched for items matching <em>${term}</em>. Found <strong>${profiles.size()}</strong> hits. 10 </p> 11 <ul> 12 <g:each var="profile" in="${profiles}"> 13 <li>${profile.fullName}</li> 14 </g:each> 15 </ul> 16 <g:link action='advSearch'>Search Again</g:link> 17 </body> 18 </html>
2、Projections(投影)
投影被用于定制查询结果。要使用投影你需要在criteria builder树里定义一个"projections"节点
1 def tagList = Post.withCriteria { 2 createAlias("user", "u") 3 createAlias("tags", "t") 4 eq("u.userId", "glen") 5 projections { 6 groupProperty("t.name") 7 count("t.id") 8 } 9 }
3、HQL
硬编码
def results = Book.findAll("from Book as b where b.title like 'Lord of the%'")
位置参数
def results = Book.findAll("from Book as b where b.title like ?", ["The Shi%"])
命名参数
def results = Book.findAll("from Book as b where b.title like :search or b.author like :search", [search:"The Shi%"])
多行
1 def results = Book.findAll("""\\ 2 from Book as b, \\ 3 Author as a \\ 4 where b.author = a and a.surname = ?""", ['Smith'])
分页排序
def results = Book.findAll("from Book as b where b.title like 'Lord of the%'", [max:10, offset:20, sort:"asc", order:"title"])
4、总结和最佳实践
- Use scaffolds for instant gratification and to stay motivated:使用动态脚手架能给开发者带来惊喜,如果愿意就尽量使用吧
- Understand your customization options:可以使用调整css的方法调整界面,也可以修改脚手架模板代码改善脚手架生成的外观,只要愿意
- Dynamic finders are fantastic for two-field queries:动态查询器比较适合两个参数的查询
- Use the Grails console:善用console可以帮助我们调试程序
- Harness the power of criteria queries:提高使用criteria queries的能力,因为那很重要
- Always use named params for HQL:慎用HQL,除非其他方法不能解决,如果一定要用,要使用命名参数,防止SQL注入攻击
- Use bootstraps conditionally:使用bootstrap加入原始数据时,带入环境条件,避免测试数据在生产环境出现
5、代码清单
domain
package:com.grailsinaction
Post
Profile
User
Tag
controllers
package:com.grailsinactin
PostController
ProfileController
UserController
TagController
views
layout
main.gsp
user
advResults.gsp
advSearch.gsp
results.gsp
search.gst
error.gsp
test/integration
package:com.grailsinaction
PostIntegrationTests
UserIntegrationTests
QueryIntegrationTests
web-app
css
hubbub.css
images
backgroud.png
headerlogo.png
6、代码打包下载