2012-04-03 7 views
0

私はかなり長い間、Hibernate 4.1.1で作業しています。 以下:私は、HibernateのIntegrator Interfaceによって統合されたEventListenerを作成しました。これまでのところ、これは動作します!EventListenerのエンティティを削除する

私は、アカウントなどのエンティティを削除しようとしています。 アカウントはプレイリストと1対1の関係にあります。

達成したいこと: アカウントを削除するとプレイリストが削除されます。

私は、私がHibernate Mappingsにカスケード動作を追加することでこれを達成できることを知っています。 これまでのところ、これは動作しますが、Hibernateがカスケードにnull値を設定するための機能を提供することができないので、私は手動でこれらのステップをやってみたかった:

@Override public boolean onPreDelete(final PreDeleteEvent preDeleteEvent) throws HibernateException 
{ 
    if (preDeleteEvent.getEntity() instanceof PresetEntry) { 
    } else if (preDeleteEvent.getEntity() instanceof AccountEntry) { 
     final Session session = this.sessionFactory.getCurrentSession(); 

     if (!session.getTransaction().isActive()) { 
      session.getTransaction().begin(); 
     } 
     final AccountEntry accountEntry = (AccountEntry) preDeleteEvent.getEntity(); 
     session.createQuery("DELETE FROM PlaylistEntry WHERE ACCOUNT_ID = " + accountEntry.getIdentity()).executeUpdate(); //NON-NLS 
    } else if (preDeleteEvent.getEntity() instanceof PlaylistEntry) { 

    } else if (preDeleteEvent.getEntity() instanceof QueueEntry) { 

    } 
    return false; 
} 

私は問題を以下で実行している:

アカウントは現在、(それが延々と削除playlistEntryクエリをコミットしています)
  • クエリがコミットされていない場合にStackOverflowErrorでonPreDelete結果内のコミット呼び出し
  • が削除されるため
    1. は、トランザクションがすでに開いていますonPreDeleteメソッド内ではクエリが実行されますが、Swingアプリケーションは永遠にフリーズし始めます。

  • は、だから私はそれをどのように解決することができ、外部キーアクションなし例外でプレイリストの結果を削除しませんか?

    +0

    現在、あなたのコードは 'カスケード'で実現できますか? –

    +0

    @EugeneRetunskyそれは絶対に正しいです!しかし、カスケードなしでそれを行うことで達成可能ではないのでしょうか? Hibernateのカスケード機能には、あまりにも多くのSQLカスケード機能がありません(たとえば、ON DELETE | UPDATE SET NULLなど) –

    答えて

    1

    コミットトランザクションのStackOverflowは、onPreDeleteハンドラをもう一度(何度も何度も)呼び出すために発生します。このオブジェクトの削除をすでに処理したことをリスナー内部で検出する必要がないようにするためです。これは、次のようなアプローチによっていずれかを行うことができます(それはハッシュコード+実装等しいを持っている場合)もちろん

    private final Collection<Long> processingAccounts = 
         Collections.newSetFromMap(new ConcurrentHashMap<Long, Boolean>()); 
        ... 
        @Override public boolean onPreDelete(final PreDeleteEvent preDeleteEvent) 
         throws HibernateException { 
         .... 
        } else if (preDeleteEvent.getEntity() instanceof AccountEntry) { 
          // check if it's already been processed 
          if (processingAccounts.contains(preDeleteEvent.getEntity().getId()) 
           return false; 
          // block it by ID 
          processingAccounts.add(preDeleteEvent.getEntity().getId(); 
          try { 
    
          .... 
          } finally { 
           // release 
           processingAccounts.remove(preDeleteEvent.getEntity().getId() 
          } 
        } 
        return false; 
    } 
    

    は、あなたが複合キーまたはエンティティによってそれをロックすることができます。しかし、これはどのように解決できるのかという一般原則です。

    +0

    thxがたくさんあります。しかし、私は今、休止状態のセッションでトラブルシューティングをしています。メソッド#1はトランザクションを開始し、session.delete(AccountEntry)を呼び出してトランザクションをコミットすることで終了します。この削除イベントは、メソッド#2- onPreDeleteをトリガします。ここでトランザクションを開始している場合、TransactionException:サポートされていないネストされたトランザクションがスローされます。session.delete(X)を呼び出すだけの場合何も起こっていません。メソッド#2の中でコミットしている場合、メソッド#2の削除イベントが実行されますが、メソッド#1はセッションを閉じています!例外。解決策:第2セッションを開く - 動作します。 –

    関連する問題