Grails: Nullable 屬性導致 Unique 限制式失效

Grails 版本: 2.3.11

當 domain 中 unique 條件關聯的屬性包含了 nullable 類型,

grails 會忽視 unique 限制導致誤判,

根據 api 可在 constraints 中加入 validator 來自定義需要驗證的內容。

假設 Domain 定義如下:

Book.groovy
1
2
3
4
5
6
7
8
9
10
11
12
class Book{

  String name
  String title
  Author author
  Publisher publisher

  static constraints = {
      name(unique:['author','publisher'])
      publisher nullable:true
  }
}

由於 publisher 允許為 null,造成 name(unique:['author','publisher'] 沒有正確判斷,

此時可以自行加入判斷如下:

start:8
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
   static constraints = {
      name(unique:['author','publisher'],
          validator: { name, book ->
              def existingRecord = Book.withCriteria(){
              
                  if (book.id){
                      ne('id', book.id)
                  }

                  eq('author', book.author)

                  if (book.publisher){
                      eq('publisher', book.publisher)
                  }
                  else {
                      isNull('supplier')
                  }
              }//end withCreiteria
          }//end validator
      )
      publisher nullable:true
  }
}

完成後就可以正確判斷 unique 摟~

峇里島 Day 1。印尼航空&好好海鮮餐館鹹蛋螃蟹

拖了好久才開始動工的峇里島遊記~

選擇了印尼航空的轉機行程,除了省錢之外也希望可以增加一些搭機的經驗,

(結果明明就驚慌失措嚇得半屎)

關於我們嚇死人不償命的轉機大冒險可以參考這篇 印尼航空(Garuda Indonesia)。雅加達轉機峇里島去回流程

第一天基本上就是在搭機中度過,先來一張台灣的海岸線~

印航不時會提供一些小點心,早上有一包辣辣的果仁零食,下午還有糖果、飲料、 Häagen-Dazs 冰淇淋~

(拿相機對著空姐真的需要臉皮很厚)

台灣-雅加達的班機會提供餐點 menu ,雅加達-峇里島則沒有,但兩段航程都有提供飛機餐喔。

只有拍去程的,回程的部分看了我的轉機奇遇記之後就可以理解我根本沒力氣拍阿!! XDD

有中式口味和印尼口味,印象中都是印尼口味比較好吃,

印尼餐點的神奇在於本來不好吃的東西只要加了ABC辣醬味道都超合 (個人覺得) ,算是走重口味路線。

飲品的部分選擇也蠻多的,去回總共吃了四次的飛機餐,我和小狐狸每次都點不同的嚐鮮,

Guava Juice 紅芭樂汁:五顆星

Bintang 印尼啤酒:四顆星

少一顆的原因是因為… 大家到了國外常會說當地的啤酒多好喝好喝,

可是我個人挑戰完的心得是只要新鮮又冰的啤酒都很好喝~ :P

日本、大陸、印尼的啤酒都偏淡,是覺得好喝但沒有特別驚豔 XD

Santa Carolina 紅酒:四顆星 以飛機上的紅酒來說很值得喝一下~

Gordon’s Dry Gin 琴酒:零分 哈…

好奇心驅使點來喝,空姐有問要不要加其他東西 (琴酒適合做基酒) ,

但我想喝喝看琴酒本身的味道便拒絕了,結果真的是超.難.喝 (空姐我錯了)

有一種薑味混合藥草的感覺。


雅加達海岸線,那一大坨的灰蒙蒙的土是正在進行的填海工程。

走進雅機達機場立馬看到傳統雕刻藝術~ (峇里島機場更誇張外觀跟廟差不多)

印尼是個宗教國家,宗教與政治關係密不可分,正好可以從公共建築形式印證,

導遊還跟我們說當地總統候選人一定得是回教徒, (雖然我上網查好像沒有一定拉,只是因為印尼伊斯蘭教佔大宗)

在機場也可以看到超多伊斯蘭教徒,想像一下這時候暑假大熱天的,

伊斯蘭教女人卻要全身包緊緊的,真的很辛苦~而且裡面還有穿便服,我都要替他流汗了~~ orz

(話說我偷拍北鼻大姐怎麼看鏡頭呢)

由於一夫多妻制,在機場排隊時也常看到一個先生後面站了好幾個太太的有趣畫面,

老公穿的一身帥氣,老婆卻只能烏漆麻黑!! (淚)

過海關時只要先生代表就可以通關,一個人拿五本護照好像很帥氣!!

不過在回程時也有看到海關要求太太過去露臉的,

太太看起來很痛苦緩慢的移動面罩,先生則很心疼一手撫著太太的頭避免被海關以外的人看見,

面罩拉了一半左右海關便立馬揮揮手示意可以了,

真是有趣的人生觀察。

到峇里島摟~偷拍了有點正但好像不太開心的空姐~晚上的飛機好像也有點漂亮,嘻嘻 :D


出機場之後已經快九點多了,第一天的行程就只有晚餐而已,

本來安排的是 hard rock 的 buffet ,但是我們才在飛機上吃過晚餐欸欸欸~

後來導遊說因為太晚了 hard rock 已經打烊,因此改吃螃蟹餐,

我們還暗暗竊喜了一下,想說這樣分量應該不會太多,沒想到根本大錯特錯,

而且這一餐也是整個行程下來吃最好的一餐 –_______–

餐廳的招牌寫著大大的中文字:好好海鮮餐館,

在毫無心理準備的情況下,服務生上菜有如滔滔江水綿延不絕~

菜色如下:

玉米濃湯、鹹蛋螃蟹、辣醬蝦、炸魚、燴豆腐、辣醬空心菜、蒜炒油菜、白飯、茶、水果

看看我們兩個人要吃完誇張的整桌菜,而且還吃過晚餐,是豬逆

最後還是棄械投降請導遊和司機一起幫忙解決。


相關文章:

印尼航空(Garuda Indonesia)。雅加達轉機峇里島去回流程

2014 信用卡國際機場外圍免費停車

2014 信用卡國際機場外圍免費停車-富邦數位生活卡

富邦銀行

數位生活卡

刷卡支付當次出國航程全額機票或80%,

鈦金卡可享每年不限次數、每次7天之免費停車優惠

白金卡可享每年2次、每次7天之免費停車優惠

我和小狐狸都是 MasterCard ,但一張是綠色一張是藍色,

綠色的是鈦金卡,藍色則是白金卡,(額度的差別)

這次我們刷的是白金卡,配合的是東航國際機場專屬停車場,距離機場大約5分鐘車程,

場地看起來有點舊舊的,車子停好後填寫信用卡資料就可以了~會有 24hr 接駁車去回接送。

回國領完行李就可以打電話請接駁車過來,出發跟回程幾乎都沒什麼等就上車了,整體來說很滿意~

接送司機的服務態度意外的很不錯 (給一個大拇哥) 。

機場接駁上下車在同一個地方,

但我自己覺得路線還蠻不好記又沒有明顯指標,還特地拍了一張照避免回程找不到,哈哈。

東航國際機場專屬停車場

地址:桃園縣大園鄉三民路二段69號

電話:0800-022-999(03)383-8888

點我查看富邦卡友權益

印尼航空(Garuda Indonesia)。雅加達轉機峇里島去回流程

[貼心小提醒] 如果沒有時間看夏天落落長歷險記的話 :P 可點此觀看流程精簡版

印航今年推出了台北到峇里島的優惠票價,

代價就是需要在雅加達轉機,含轉機等候至少會比直飛多花四小時的時間,

因為過去也有不少搭飛機的經驗,心想應該不會太困難,

我原先訂的團體行程沒有成行,導致後面改訂 mini tour 的時間很緊湊,

與旅行社只透過網路及電話聯絡,對方也沒有交代什麼需要注意的細節,

由於 mini tour 兩人就能成行所以台灣不會派領隊,

我們的團費包含來回機場稅及離境稅RP.15萬/人,但不含落地簽USD.25/人

去程

到了桃園機場先去印航掛行李的櫃檯,將電子機票交給櫃檯地勤領取登機證,並交代行李直掛峇里島。

然後就可以開開心心上飛機摟~

抵達前一小時左右空姐會發三聯式的出入境卡(ARRIVAL-DEPARTURE CARD)海關申報單(CUSTOMS DECLARATION)

在機上先填好,雅加達下飛機之後,很快就能看到 VISA ON ARRIVAL 指標,左右兩邊都有,

同行可以由一人代表排隊購買,出示護照、付錢之後會拿到簽證收據,

我們以為轉機不用入境,所以一直尋找轉機的指標,

但轉機入口都被封鎖,只剩下海關通道可以走,

詢問了幾個機場人員後,原來必須先入境 (後來了解是因為國際線轉國內線的緣故),

在 Foreigner 看板前排隊,需要出示護照、登機證、出入境卡,

海關檢查蓋章後會退還第三聯出境卡(Departure Card)這張卡要保留到回程離境時使用,

我在峇里島時還有想把他丟掉的念頭 (汗…)

過海關後印象中沒有什麼明顯的指標,要先往左邊走,

我們又開始東張西望尋找轉機的字樣,

大概是不時流露出疑惑的表情,有幾個身上穿著像清潔工制服寫著 XXX Service 的人經過我們身邊時會對我們說一些聽不懂的話,

我們沒搭理繼續往前走,走到底便看到一個 check 隨身行李的通道,

正當我們猶豫著是否要進去時,又有一個一樣是 XXX Service 的直接過來拿了我的護照跟機票,

一路帶我們快速通關,先是通過隨身行李檢查,接著再到另一個入口檢查登機證 (印象中也是往左邊走有個小小的門),

到這邊 Service 先生突然開口和我要小費並且手舉高高的拿著我們的機票,

我當下整個愣住幾秒,跟他說我還沒有換錢,心裡超害怕他沒收我的機票 XDD

隨後他面無表情把機票還我走人,真是老天保佑! T___T

看到 transfer 的指標後坐手扶梯上樓,發現跟先前被封鎖的入口是通往一樣的地方,

上去很快就往登機門的方向繼續走,快到登機門前會再遇到一次檢查隨身行李的關卡,

想尿尿記得先去!因為過關卡後就沒有洗手間了~囧

我們傻傻的進去之後等一個多小時還不能尿尿啊~~~(吶喊)

再次搭上前往峇里島的飛機,領完行李莫名就走到出口直接看到導遊~~

回程

前面提到團費已經包含離境稅,於是我們天真的以為包含離境稅是指旅行社會處理好的意思,

就完全沒理會也沒做功課,回程這天旅行社派了個小弟在機場帶我們,

導遊塞了一把錢給他之後,我們就跟著他去領登機證、掛行李,之前會先經過一次隨身行李檢查,

處理好之後他指示我們進入另一道隨身行李檢查便跟我們道別,

此時我有點疑惑落地簽有收據那麼離境稅怎麼沒有?

但秉持著我們要相信專業的精神便不疑有他繼續走下去,(其實是因為小弟中英文都很爛阿!!)

接著一路依照登機門指標順利上了飛機,

抵達雅加達後就跟著 transfer 的指標走,我們的登機門是 E4,先遇到了 F 系列登機門,

好不容易才看到一個E系列指標,經過一連串的貴賓休息室,竟然就走到底了?

剩下左邊有一個小小的路可以走,接著右轉,會看到蠻多航空公司的櫃檯,

不過完全沒有登機門的指標就是,鼓起勇氣繼續往前走下去,

走到底發現海關檢查處,看到E指標就在海關後面,表示應該是需要先出境,

排隊輪到我時,海關拿出一張卡在我面前晃了一下,示意要我交給他,當下一時慌張以為是需要離境稅收據,

轉頭向小狐狸求救,小狐狸從他的護照抽出來一張一樣的,我才發現是離境卡 (Departure Card),

因為海關當時翻的是背面給我看導致我大誤會 (恥) ,趕緊把卡交出去就通過了,這可是我差點想丟掉的卡啊啊啊~好恐怖噢!

由於距離登機時間還有一個小時左右,加上去程的經驗只要過了隨身行李檢查關卡就不能尿尿了

我又很倒霉的遇到生理期,身上的好自在有限,因此拖到最後一刻去完廁所才進去,

登機時間是 13:50 ,起飛時間是 14:10 ,

這邊除了經過隨身行李檢查關卡外,會有警衛二次檢查,需要把包包打開給他看,

我看別人跟小狐狸都有被翻包包,但是我的包包一打開就是好自在啊~,

警衛好像不好意思翻,就直接整個拿著東張西瞧了一段時間才讓我進去,

印航地勤檢查機票之後,指示我們到櫃檯去,此時一個會說中文的漂亮地勤告訴我們需要付離境稅,

我們當下都傻住,告訴她說離境稅應該是導遊幫我們付了,

她讓我們請導遊過來櫃檯,可是導遊在峇里島啊啊!! XDD

她告訴我們離境稅是在雅加達機場才付的,導遊應該要給我們錢,

我只好拿出導遊的電話號碼請她幫我聯絡,美女地勤人超 nice 立馬就打了電話,

導遊說他要打去公司詢問一下機場小弟狀況,我可是等到最後的登機時間才進入,剩下不到十分鐘啊!

美女地勤問我們如果來不及該怎麼辦,我們告訴她我們身上完全沒有現金只有信用卡,大家都囧了…

因為我們錯估此行花費,換的錢太少,盧比不夠連台幣都拿出來花了還刷卡,

於是她又再次打給導遊,導遊詢問地勤是否可以先支付我們的稅金再匯款還她,

但她跟我們說她忘記她的密碼,雖然聽起來很扯,但我總覺得她很誠懇,

一方面我們只是過路客,對他來說很為難也是理所當然,

於是我們決定先到提款機領錢看看,還回到海關詢問哪邊可以繳離境稅,

結果竟然是在登機門地勤那邊繳就可以了 (為了怕有人事先忘記繳,例如我們?)。

試了好幾張卡竟然都無法領,小狐狸決定再回到登機門詢問狀況,

我則繼續試剩餘的卡,仍然徒勞無功,所以我也回到登機門去,

經過檢查機票人員時看到一位穿紅色襯衫的先生,衣服有種印尼傳統服飾融合夏威夷風格,

當下覺得他是機場相關人士或是旅行社之類的人物,以為他可能在幫忙溝通我們的狀況之類的或是湊熱鬧?,

走到櫃檯時小狐狸說好了沒事了,我問怎麼突然可以了?

然後美女地勤說了一些某某人搞錯之類的話,我:好險,卡全部都領不出錢。

此時美女地勤嚇到,原來她是以為我帶著錢回去才說好了,

於是我們大家又開始陷入一陣慌張,幸運的是班機延誤還沒開始登機,不然我們可能直接被遺棄在雅加達,

美女地勤一直表露出想幫助我們的感覺,但又不能置自己於風險中?XD

我可以體會她的心情,但眼下也想不出其他辦法,於是我問她是否可以請她先幫我們付,如果導遊沒有匯給他我再補匯,

(話說這是因為當下大家都認為一定是導遊A走我們的離境稅XDD,但是我感覺我們導遊不是那種人~)

但她還是說忘記密碼之類的@@,現在回想應該是想表達忘記銀行帳號所以無法給我,也無法給導遊,(畢竟不是中文不是她的母語)

後來她建議我們是不是可以跟同班機的台灣旅客借錢,

嗯,的確是個辦法,但是要和素不相識的陌生人要開口借錢真的是需要恥力滿點!!! >“<

同班機有個女導遊,小狐狸覺得可以先跟她借看看,

女導遊表現出尷尬,說她沒有那麼多錢 (RP$300,000),其實折合台幣大概是 800 到 1000 而已,

之後又說她身上有錢,但那是要交回公司的,

當下我們真的非常無助,她雖然不想借但看得出有點掙扎,

然後紅色襯衫先生突然出現了說他願意跟我換盧比,要我給他台幣 800,

我說我身上只剩下 300 台幣,於是又問女導遊說是否可以借我們 500,

(因為我們以為紅色襯衫先生是機場相關的人要還錢給他比較不方便)

女導遊卻說為什麼要這麼麻煩,你們彼此之間處理就好了啊,

同時竟然落井下石的質問地勤為什麼飛機 delay 這麼久,不斷問她還要多久才能飛,

當下我跟小狐狸非常傻眼尷尬,是想讓我們回不了家逆!

後來紅色襯衫先生才發現我們身上沒錢,他說沒關係之後再還就先幫我們付了,

是不是該掉個兩滴淚!

一問之下才知道原來他是印尼人要去台灣旅遊,我們立刻表示一下飛機就可以領錢還他,真的大大感恩!

整個心情非常複雜,很難過想哭也很感動,

難過的是為什麼台灣人不能互相幫助,我相信 500 元對一個成年人來說是可以負擔的,

也感動素昧平生的外國人願意相助,而且還是生活在社會較不安定的印尼人,

登機前導遊再次來電詢問我們狀況,可以聽得出來他非常緊張一直跟我說對不起,

我告訴他有人借我們錢了,請他不要擔心,他表示是機場小弟忘了給我們錢,之後會把離境稅補匯給我們,

就這樣帶著緊繃的心情平安回到家。

後記:導遊真的有把錢匯還給我們~不過他用當地匯率算,所以只有匯來720台幣,

由於是用較快速西聯匯款,他還要負擔手續費也蠻貴的,所以就算摟~

去回轉機流程精簡版

台北-雅加達-峇里島

  1. (桃園機場) 帶電子機票到印航櫃檯領登機證及掛行李,並告知直掛峇里島。

  2. 飛機上索取並填寫出入境卡(ARRIVAL-DEPARTURE CARD)海關申報單(CUSTOMS DECLARATION),正常是空姐會發。

  3. 下飛機 (雅加達機場) 依 VISA ON ARRIVAL 指標到櫃檯買落地簽USD.25/人,需準備護照。

  4. 過海關入境,需準備護照、登機證、出入境卡、海關申報單、簽證收據,海關退還的離境卡 (Departure Card) 要留到回國那天使用。

  5. 往左邊直走到底,在右邊通過隨身行李檢查。

  6. 往左邊走到一個小門之類的?要檢查登機證。

  7. 跟著transfer指標走到登機門。

  8. 下飛機 (峇里島機場) 領完行李直接走出去。

峇里島-雅加達-台北

  1. 旅行社小弟帶我們進入機場,需檢查護照,看其他網友自助的經驗是要出示電子機票開票證明。

  2. 到印航櫃檯領機票、掛行李。

  3. 經過隨身行李檢查處。

  4. 下飛機 (雅加達機場) 後到印航櫃檯購買離境稅RP.150,000/人。(這邊實際路線我就無法描述摟~)

  5. 跟著 transfer 指標走,接著到海關出境,但沒有明確指標,需出示護照、登機證、離境卡 (Departure Card)。

  6. 過了海關跟著指標走到登機門,會經過一處隨身行李檢查,再經過一處警衛檢查,需出示護照。

  7. 將機票交給地勤人員檢查,忘記買離境稅可以在登機門的櫃檯買。

  8. 下飛機 (桃園機場) 領行李、檢查行李,下次再見摟。


相關文章:

峇里島 Day 1。印尼航空&好好海鮮餐館鹹蛋螃蟹

2014 信用卡國際機場外圍免費停車

Ext JS: Store loadData() Id 重複導致只顯示一筆資料

Ext JS 版本: 4.2.x

Sencha Architect 版本: 2.2.3

此處希望建立一個共用的 grid 來顯示不同 table 的資料,

如下 Json Data 所示:

Json Data
[{"id":1, "name": "Java Programming", "title": "Java 程式設計"},
 {"id":1, "name": "Fashion Magazine", "title": "時尚雜誌"}]

在執行 grid.getStore.loadData(record) 後卻只有顯示一筆資料,

檢查後發現是 id 重複造成,

由於資料存於不同的資料表,因此後端 query 出預備載入的 record 便可能會有重複 id ,

API 說明 proxy 中 reader 的 idProperty 設定,是用該欄位作為 record 的唯一識別值,預設為 id 欄位,

因此我們可以將 idProperty 定義為實際的唯一識別欄位,避免相同 id 的資料被覆蓋,

由於我的 record 並沒有唯一識別值,暫時設置為 undefined。

book update
1
2
3
4
5
6
7
8
proxy: {
  type: 'memory',
  reader: {
      type: 'json',
      idProperty: 'undefined'
  }
}

另外 API 也提到 store.loadData(record) 定義為預設資料已經處理成正確格式,

因此不會經過 reader 二次處理,

若希望使用 reader 處理,需改為使用 store.loadRawData(record)