2012-12-05 153 views
5

當在我瘋狂的宇宙間可以有很多椅子和椅子可以「屬於」到很多房間走走參照完整性約束違規「。 在grails中看起來像這樣。椅子不應該知道他們屬於哪個房間。刪除域對象

class Room { 
    String name 
    static hasMany = [chairs: Chair] 
    static constraints = { 
    } 
} 
class Chair { 
    String name 
    static constraints = { 
    } 
} 

我想要刪除椅子並自動刪除所有具有該椅子的房間域對象中的椅子引用。 我已經成功,但有一個我不喜歡的修復程序。在ChairController我做了以下

def deleleChair(){ 
    def chairToDelete = Chair.get(params.id) 
    Room.findAll().each {room-> 
     if(room.chairs.contains(chairToDelete)){ 
      room.removeFromChairs(chairToDelete) 
      room.save(failOnError:true) 
     } 
    } 
    chairToDelete.delete(params.chairId) 
} 

是否有一個休眠配置,我需要設置,以便它自動執行此操作?這似乎是在現實世界中非常普遍的情況。當我可能決定時,我不想實現同一段代碼(瘋狂的例子),一個Car域對象可以有多個椅子。

我曾嘗試使用Grails事件推插件。我有一個ChairService,在gorm中偵聽beforeDelete事件。

class ChairService { 
    @grails.events.Listener(topic = 'beforeDelete', namespace = "gorm") 
    def handleDeletedChair(Chair chair){ 
     Room.findAll().each {room-> 
      if(room.chairs.contains(chairToDelete)){ 
       room.removeFromChairs(chairToDelete) 
       room.save(failOnError:true, flush:true) 
      } 
     } 
    } 
} 

該功能被稱爲每當椅子刪除嘗試,但當它返回ChairController這樣做實際的椅子上刪除,刪除操作仍然認爲,提及間仍然存在,並拋出一個

Caused by JdbcSQLException: Referential integrity constraint violation:"FK4ACA6A6151428364: PUBLIC.ROOM_CHAIR FOREIGN KEY(CHAIR_ID) REFERENCES PUBLIC.CHAIR(ID)"; SQL statement: 

從椅子上刪除其中id =?和版本=? [23503-164]

我想這個邏輯是分開的主席,主席應從來沒有對酒店客房。

+1

如果你不在意主席可以看到房間,這會變得更容易。 – Gregg

回答

1

簡單的解決辦法是使用標準的SQL:

import grails.events.Listener 
import groovy.sql.Sql 

class ChairService { 
    def dataSource // autowired 

    @Listener(topic='beforeDelete', namespace='gorm') 
     def handleDeletedChair(Chair chairToDelete) { 
     new Sql(dataSource).execute('DELETE FROM room_chair WHERE chair_id=?', [chairToDelete.id]) 
     return true 
    } 
} 

由於這是SQL這可能取決於你所使用的數據庫(我用H2測試)。

+0

我試過這個,它完美的作品 – user1879106

1

因爲關係不存在雙向我不知道有一個更好的解決方案。

但是,如果你正在處理大量的客房/張椅子,我會建議使用具有突出條件查詢加載了只有你想要刪除的,而不是裝載了所有房間,椅子的IDS。 更好的使用executeUpdate方法做一個「散」刪除。這樣做也應該有助於解決您的錯誤。

grails criteria query docs...

deleting objects in grails docs...

0

我陷入了ChairController.delete的錯誤,這是拋出錯誤。 刪除發生,關聯被刪除,但引發了錯誤。 我的解決方案非常討厭,我基本上發現了異常,並在之後提供了相關視圖。

Caused by HibernateOptimisticLockingFailureException: Object of class [test.cascade.Chair] with identifier [2]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [test.cascade.Chair#2] 
->> 10 | doCall    in test.cascade.ChairService$_handleDeletedChair_closure1 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|  7 | handleDeletedChair in test.cascade.ChairService 
| 238 | invoke . . . . . . in org.grails.plugin.platform.events.registry.DefaultEventsRegistry$ListenerHandler 
| 159 | invokeListeners in org.grails.plugin.platform.events.registry.DefaultEventsRegistry 
|  69 | event . . . . . . in org.grails.plugin.platform.events.publisher.DefaultEventsPublisher 
| 149 | event    in org.grails.plugin.platform.events.EventsImpl 
|  70 | onApplicationEvent in org.grails.plugin.platform.events.publisher.GormBridgePublisher 
| 1110 | runWorker   in java.util.concurrent.ThreadPoolExecutor 
| 603 | run . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run    in java.lang.Thread 

Caused by StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect): [test.cascade.Chair#2] 
->> 10 | doCall    in test.cascade.ChairService$_handleDeletedChair_closure1 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - 
|  7 | handleDeletedChair in test.cascade.ChairService 
| 238 | invoke . . . . . . in org.grails.plugin.platform.events.registry.DefaultEventsRegistry$ListenerHandler 
| 159 | invokeListeners in org.grails.plugin.platform.events.registry.DefaultEventsRegistry 
|  69 | event . . . . . . in org.grails.plugin.platform.events.publisher.DefaultEventsPublisher 
| 149 | event    in org.grails.plugin.platform.events.EventsImpl 
|  70 | onApplicationEvent in org.grails.plugin.platform.events.publisher.GormBridgePublisher 
| 1110 | runWorker   in java.util.concurrent.ThreadPoolExecutor 
| 603 | run . . . . . . . in java.util.concurrent.ThreadPoolExecutor$Worker 
^ 722 | run    in java.lang.Thread