2012-12-05 12 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) 
} 

私は、これは自動的にないように設定する必要が休止状態の設定はありますか?実際のシナリオでは非常に一般的なもののようです。カードメインオブジェクトが多くの椅子を持つことができると私はおそらく決める(狂気の例)、私は同じコードを実装したくないです。

私はgrailsイベントプッシュプラグインを使用しようとしました。私は、GormのbeforeDeleteイベントを聞いた行動でChairServiceを持っていました。

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を使用することです。

+0

私はこれを試して、それは完全に動作します – user1879106

1

この関係は双方向に存在しないため、はるかに洗練されたソリューションがあるかどうかはわかりません。

しかし、たくさんの部屋/椅子を扱っている場合は、すべての部屋を椅子に載せるのではなく、削除したいIDだけを読み込むために、投影を伴う条件クエリを使用することをおすすめします。 さらに良いですが、executeUpdateメソッドを使用して、一括削除を実行します。これを行うと、エラーにも役立ちます。

grails criteria query docs...

deleting objects in grails docs...

0

私はChairController.deleteでエラーをキャッチし、これがスローされるエラーです。 削除が行われ、関連付けは削除されますが、優先権がスローされます。 私のソリューションはかなり厄介ですが、私は基本的に例外をキャッチし、後で関連するビューをレンダリングしました。これは、それはあなたが使用しているデータベースに依存する可能性があるSQLであるので(私はH2でテスト済み)

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 
    } 
} 

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 
関連する問題