删除域对象和外键

时间:2012-10-03 15:25:55

标签: hibernate grails orm groovy

我有一个中等复杂的设计,我试图从系统中删除“ItemCollection”。此对象属于发布者(一对多),具有MediaItems(一对多)和Posting(一对一)。过帐由非拥有多对多中的其他2个对象引用。

当我删除I​​temCollection(通过在父级上调用removeFrom())时会触发级联,但我最终会在多对多集合中使用外键异常。我已经尝试从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 >>
}

这两个类引用了过帐。

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

我已将以下内容添加到发布中。

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时,我得到以下stacktrace:

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

2 个答案:

答案 0 :(得分:0)

您可能不应该使用两个会话。我不认为hibernate会保证在删除Posting对象之前刷新在beforeDelete处理程序中创建的会话。如果您不需要两个单独的会话,请使用withSession代替withNewSession

答案 1 :(得分:0)

原来有另一张表被引用,我没有处理。澄清上面的答案 - withNewSession是在这里使用的正确习惯用法,你不想在beforeDelete方法中保存(flush:true)。