6

私のクレイジーな宇宙では、部屋には多くの椅子があり、椅子は多くの部屋に「属する」ことができます。グレイルではこんな感じ。椅子は、自分がどの部屋に属しているかを認識してはなりません。

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 イベント プッシュ プラグインを使用しようとしました。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 に戻ると、削除アクションは引き続き Room への参照がまだ存在すると見なし、

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

id=? の椅子から削除 バージョン=? [23503-164]

私はこのロジックを椅子とは別にしたいと思っています。

4

3 に答える 3

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 でテストしました)。

于 2012-12-07T09:02:37.687 に答える
1

この関係は双方向に存在しないため、もっと洗練された解決策があるかどうかはわかりません。

ただし、多くの部屋/椅子を扱っている場合は、すべての部屋に椅子をロードするのではなく、プロジェクションを使用して条件クエリを使用して、削除する ID のみをロードすることをお勧めします。メソッドを使用しexecuteUpdate「一括」削除を行うことをお勧めします。これを行うと、エラーにも役立ちます。

Grails 基準クエリ ドキュメント...

grails ドキュメント内のオブジェクトを削除しています...

于 2012-12-06T01:18:57.047 に答える
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
于 2012-12-07T06:32:31.797 に答える