やや複雑な設計で、システムから「ItemCollection」を削除しようとしています。このオブジェクトは Publisher (1 対多) に属し、MediaItem (1 対多) と Posting (1 対 1) を持ちます。投稿は、非所有の多対多で他の 2 つのオブジェクトによって参照されます。
(親で removeFrom() を呼び出して) ItemCollection を削除すると、カスケードがトリガーされますが、多対多のコレクションで外部キー例外が発生します。beforeDelete() で他のコレクションから Posting を削除しようとしましたが、ログ出力はこれが機能していることを示していますが、外部キー例外は引き続き発生します。
主な階層は次のとおりです。
class Publisher {
String name
static hasMany = [collections : ItemCollection, defaultTags : MetaTag, feeds : Feed]
static mapping = {
collections cascade: 'all-delete-orphan'
}
}
class ItemCollection {
static hasOne = [posting:Posting]
static hasMany = [items:MediaItem, tags:MetaTag]
static mapping = {
items sort:'collectionOrder', order: 'asc', lazy:false, cascade: "all-delete-orphan"
posting cascade: "all-delete-orphan"
tags lazy:false
}
static belongsTo = [publisher:Publisher]
}
class Posting {
static belongsTo = [itemCollection: ItemCollection]
<< see beforeDelete method below >>
}
Posting は、これら 2 つのクラスによって参照されます。
class ItemFeed {
List posts
static hasMany = [posts:Posting, segments:FeedSegment]
static mapping = {
segments cascade: 'all-delete-orphan'
posts lazy:'false'
}
static constraints = {
posts nullable:true
segments nullable:true
}
}
class FeedSegment {
Date postingTime
String s3objname
List posts
static belongsTo = [feed:ItemFeed]
static hasMany = [posts:Posting]
static constraints = {
posts nullable:true
}
}
私のコントローラーで私は呼んでいます:
collectionIds.addAll(params?.collectionIds)
collectionIds.each { id->
log.info("deleting ${id}")
def itemCollectionInstance = ItemCollection.get(id)
def publisher = itemCollectionInstance.publisher
publisher.removeFromCollections(itemCollectionInstance)
publisher.save(flush:true)
}
そして、次の onDelete を Posting に追加しました。
def beforeDelete() {
Posting.withNewSession {
log.info 'trying to delete posting from feeds'
Posting thees = Posting.get(id) /// using "this" seemed to not be reliable..?
log.info 'Deleting: ' + thees
def feedsWithPost = ItemFeed.createCriteria().list{
posts {
eq('id', thees.id)
}
}
def x = feedsWithPost
x.each { feed ->
log.info '#posts: ' + feed.posts.size()
feed.removeFromPosts(thees)
if(feed.validate()) {
feed.save()
} else {
log.warn "Problem with validation " + feed.errors.allErrors.dump()
}
log.info '#posts: ' + feed.posts.size() <---- THIS SEEMS TO WORK. I SEE SIZE GO DOWN
}
// repeated for FeedSegment...
}
}
ItemCollection を削除しようとすると、次のスタック トレースが表示されます。
2012-10-02 18:09:21,499 [http-bio-9090-exec-1] INFO feeds.Posting - Deleting: com.broadcastr.feeds.Posting : 2
2012-10-02 18:09:21,507 [http-bio-9090-exec-1] INFO feeds.Posting - found feeds: [<com.broadcastr.feeds.ItemFeed@7592b321 category=Arts & Entertainment city=New York City posts=[com.broadcastr.feeds.Posting : 1, com.broadcastr.feeds.Posting : 2] lastUpdated=2012-10-02 17:27:48.819 segments=[] jsonMetaData=null errors=null id=1 version=2>]
2012-10-02 18:09:21,507 [http-bio-9090-exec-1] INFO feeds.Posting - #posts: 2
2012-10-02 18:09:21,507 [http-bio-9090-exec-1] INFO feeds.Posting - #posts: 1
2012-10-02 18:09:21,508 [http-bio-9090-exec-1] INFO feeds.Posting - found feeds: [<com.broadcastr.feeds.ItemFeed@7592b321 category=Arts & Entertainment city=New York City posts=[com.broadcastr.feeds.Posting : 1] lastUpdated=2012-10-02 17:27:48.819 segments=[] jsonMetaData=null errors=grails.validation.ValidationErrors: 0 errors id=1 version=2>]
2012-10-02 18:09:21,510 [http-bio-9090-exec-1] WARN util.JDBCExceptionReporter - SQL Error: 23503, SQLState: 23503
| Error 2012-10-02 18:09:21,510 [http-bio-9090-exec-1] ERROR util.JDBCExceptionReporter - Referential integrity constraint violation: "FKFD598F4D2EE471: PUBLIC.ITEM_FEED_POSTING FOREIGN KEY(POSTING_ID) REFERENCES PUBLIC.POSTING(ID)"; SQL statement:
delete from posting where id=? and version=? [23503-164]
| Error 2012-10-02 18:09:21,512 [http-bio-9090-exec-1] ERROR events.PatchedDefaultFlushEventListener - Could not synchronize database state with session
Message: could not delete: [com.broadcastr.feeds.Posting#2]
Line | Method
->> 41 | doCall in DebugFilters$_closure1_closure2_closure5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 680 | run in java.lang.Thread
Caused by JdbcSQLException: Referential integrity constraint violation: "FKFD598F4D2EE471: PUBLIC.ITEM_FEED_POSTING FOREIGN KEY(POSTING_ID) REFERENCES PUBLIC.POSTING(ID)"; SQL statement:
delete from posting where id=? and version=? [23503-164]
->> 329 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 169 | get in ''
| 146 | get . . in ''
| 398 | checkRow in org.h2.constraint.ConstraintReferential
| 415 | checkRowRefTable in ''
| 291 | checkRow in ''
| 862 | fireConstraints in org.h2.table.Table
| 879 | fireAfterRow in ''
| 99 | update . in org.h2.command.dml.Delete
| 73 | update in org.h2.command.CommandContainer
| 226 | executeUpdate in org.h2.command.Command
| 143 | executeUpdateInternal in org.h2.jdbc.JdbcPreparedStatement
| 129 | executeUpdate in ''
| 105 | executeUpdate in org.apache.commons.dbcp.DelegatingPreparedStatement
| 41 | doCall . in DebugFilters$_closure1_closure2_closure5
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 680 | run in java.lang.Thread
| Error 2012-10-02 18:09:21,516 [http-bio-9090-exec-1] ERROR servlet.GrailsDispatcherServlet - HandlerInterceptor.afterCompletion threw exception
Message: could not delete: [com.broadcastr.feeds.Posting#2]; SQL [delete from posting where id=? and version=?]; constraint ["FKFD598F4D2EE471: PUBLIC.ITEM_FEED_POSTING FOREIGN KEY(POSTING_ID) REFERENCES PUBLIC.POSTING(ID)"; SQL statement:
delete from posting where id=? and version=? [23503-164]]; nested exception is org.hibernate.exception.ConstraintViolationException: could not delete: [com.broadcastr.feeds.Posting#2]
Line | Method
->> 41 | doCall in DebugFilters$_closure1_closure2_closure5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 680 | run in java.lang.Thread
Caused by ConstraintViolationException: could not delete: [com.broadcastr.feeds.Posting#2]
->> 41 | doCall in DebugFilters$_closure1_closure2_closure5
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 680 | run in java.lang.Thread
Caused by JdbcSQLException: Referential integrity constraint violation: "FKFD598F4D2EE471: PUBLIC.ITEM_FEED_POSTING FOREIGN KEY(POSTING_ID) REFERENCES PUBLIC.POSTING(ID)"; SQL statement:
delete from posting where id=? and version=? [23503-164]
->> 329 | getJdbcSQLException in org.h2.message.DbException
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
| 169 | get in ''
| 146 | get . . in ''
| 398 | checkRow in org.h2.constraint.ConstraintReferential
| 415 | checkRowRefTable in ''
| 291 | checkRow in ''
| 862 | fireConstraints in org.h2.table.Table
| 879 | fireAfterRow in ''
| 99 | update . in org.h2.command.dml.Delete
| 73 | update in org.h2.command.CommandContainer
| 226 | executeUpdate in org.h2.command.Command
| 143 | executeUpdateInternal in org.h2.jdbc.JdbcPreparedStatement
| 129 | executeUpdate in ''
| 105 | executeUpdate in org.apache.commons.dbcp.DelegatingPreparedStatement
| 41 | doCall . in DebugFilters$_closure1_closure2_closure5
| 195 | doFilter in grails.plugin.cache.web.filter.PageFragmentCachingFilter
| 63 | doFilter in grails.plugin.cache.web.filter.AbstractFilter
| 886 | runTask in java.util.concurrent.ThreadPoolExecutor$Worker
| 908 | run . . in ''
^ 680 | run in java.lang.Thread