2012-12-05 154 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