iT邦幫忙

DAY 21
1

邊看邊學Groovy/Grails/Gradle系列 第 18

Grails-基礎GORM Query語法介紹(criteria)及簡單搜尋表單

昨天來不及做Integration Test,今天才發現初始化的時候資料並未寫進資料庫,造成run integration test時出現NullPointerException,debug一段時間後就放棄了,直接到作者的forum po文詢問,同時自己用scaffolding出來的網頁新增幾筆資料,所幸Integration Test通過了,說明語法沒錯。

今天要繼續介紹Criteria語法以及簡單製作搜尋表單,Criteria特別適用於搜尋表單,搭配closure以及if可以輕鬆地將相對應的物件query出來,而where方法就比較麻煩,因where需要指定變數,而當搜尋欄變多時,我們無法預先知道使用者會輸入那些欄位,用where方法就必須多寫判斷式以免漏掉。
Criteria跟where差不多,差別在於條件是上where用的是operator如"==","in x..y"等,而Criteria則是用方法如eq()是代表equal, between()代表介於...之間,語法如下

(Domain Class Name).createCriteria().方法(){
and(or, not){條件式}}

或是

(Domain Class Name).withCriteria{and(or, not){條件式}}

首先先給大家看今天會用到的資料:
1.User Data

  1. Profile Data

User以及Profile一對一欄位的文字又臭又長,之後會跟大家分享如何修改

再來需要新增搜尋表單,這裡會用到一些grails的taglib,例如g:form、g:submitButton等,不過跟原本的html差異沒有很大,可能有些而外功能目前用不到,就先照作者說的做囉
新增->Groovy Server Page,請新增4個GSP於view/user底下,分別命名search, advsearch, result, advresult

  1. search表單,最簡易的表單,僅查詢userId

    <%@ page contentType="text/html;charset=UTF-8" %>

    		</tr>
    		<tr>
    			<td><g:textField name="query"/></td>	
    		</tr>
    		<tr>
    			<td><g:submitButton name="search" value="Search"/></td>
    		</tr>
    		</Table>
    	</g:form>
    </formset>
    

  1. advsearch,針對profile進行搜尋,故欄位比較多,用表格排版,另外多一個radio Button可以讓使用者選擇搜尋條件

    <%@ page contentType="text/html;charset=UTF-8"%>

    <div class="body">
    	<formset> <legend>Advance Search on Friends' Profile</legend> 
    	<g:form action="advResults">
    		<Table>
    			<tr>
    				<td>Name</td>
    				<td><g:textField name="fullName" /></td>
    			</tr>
    			<tr>
    				<td>Education</td>
    				<td><g:textField name="education" /></td>
    			</tr>
    			<tr>
    				<td>Email</td>
    				<td><g:textField name="email" /></td>
    			</tr>
    			<tr>
    				<td>City</td>
    				<td><g:textField name="city" /></td>
    			</tr>
    			<td>Query Type:</td>
                        <td><g:radioGroup name="queryType" labels="['And','Or','Not']" values="['and','or','not']" value="and" >
    

    ${it.radio} ${it.label}
    </g:radioGroup>





    <g:submitButton name="search" value="Search"/>


    </g:form>

3.再來則是要回到UserController這個class來寫一些code讓完成搜尋流程

import org.apache.jasper.compiler.Node.ParamsAction;

class UserController {

   static scaffold = true
   
   def search(){
	   //若未宣告則無法存取該網址
   }
   def advsearch(){
	   //若未宣告則無法存取該網址
   }
   def advResults(){ // 定義搜尋條件
	  def profileProps= Profile.metaClass.properties*.name
	  //從metaclass取得所有屬性並用profileProps儲存
	  def profiles = Profile.withCriteria {
		  "${params.queryType}"{
			  //從表單參數中queryType取得條件and, or, not
			  params.each{field, value-> 
				  if(profileProps.contains(field) && value){
					  //只要profile有該屬性且該屬性不是null則存入profiles
					  ilike field, value
				  }
			  }
		  }
	  }
	  return [profiles:profiles]
   }
   def results(String query){ //定義搜尋條件
	   //def users =User.where  {userId =~ "%${query}%"} .list()
	   def cusers = User.createCriteria().list{
		   		ilike "userId", "%${query}%"
		   /*where方法是operator組合條件
		    * 而criteria則是用各種方法組合條件
		    * 如ge()是">", ilike是"~=", between()是"in x...y"	
		    * eq()是"=="   
		    */
		   }
	   return [cusers:cusers,
		   	   term: params.userId,
				  totalUsers: User.count()]
   }
}

Note
1.任何view或是GSP網頁都需宣告後才能在網址列打入名稱存取,否則會找不到網頁
2.有關於搜尋參數如何處理必須對應到之前search以及advsearch form action的名稱
3.params即搜尋表單中所有參數的陣列

4.result,從UserController回傳的變數可以直接用${變數名稱}存取

<%@ page contentType="text/html;charset=UTF-8" %>


<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="main"/>
<title>Search Result</title>


  <h1>Results</h1>
  <p>
  	Searched ${totalUsers } records
  	for items matching <em>${term}</em>.
  	Found <strong>${cusers.size() }</strong> hits.
  </p>
  <Table>
  <g:each var="user" in= "${cusers }">
  <tr>
  <ul>
	<td><li>${user.userId}, ${user.password}</li></td>
  </ul>
  </tr>
  </g:each>
  </Table>
  <g:link action='search'>Search Again</g:link>

5.advresult

<%@ page contentType="text/html;charset=UTF-8" %>


<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<meta name="layout" content="main"/>
<title>AdvSearch Result</title>


  <h1>Advanced Search Results</h1>
  <p>
  	Found <strong>${profiles.size() }</strong> hits.
  </p>
  <Table>
  <g:each var="profile" in= "${profiles}">
  	<tr>
  	<ul>
  		<td>
  		<li>FullName:${profile.fullName}, 
  		Education:${profile.education}, 
  		Email:${profile.email}, 
  		City:${profile.city}</li></td>
  	</ul>
  	</tr>
  </g:each> 
  </Table>
  <g:link action='advsearch'>Advance Search Again</g:link>

i.搜尋條件1

ii.搜尋條件2


上一篇
Grails-基礎GORM Query語法介紹(where)
下一篇
Grails-基礎GORM Query語法介紹(HQL簡易語法)
系列文
邊看邊學Groovy/Grails/Gradle27

尚未有邦友留言

立即登入留言