7

次のように Hibernate Event Listener を実装しました。

public class AuditListener implements PostInsertEventListener {
  private static final long serialVersionUID = -966368101369878522L;

  @Override
  public void onPostInsert(PostInsertEvent event) {
    if (event.getEntity() instanceof Auditable) {
      StatelessSession session = null;
      try {
        session = event.getPersister().getFactory().openStatelessSession();
        Auditable auditableEntity = (Auditable)event.getEntity();
        session.beginTransaction();
        session.insert(new AuditTrail(auditableEntity.getClass().getSimpleName(),
            auditableEntity.getId(), auditableEntity.getStatus(),
            auditableEntity.getLastModified()));
        session.getTransaction().commit();
      } catch (HibernateException he) {
        System.out.println("Horrible error: " + he.getMessage());
        session.getTransaction().rollback();
      } finally {
        if (session != null) {
          session.close();
        }
      }
    }
  }
}

オブジェクトを挿入AuditTrailした直後にオブジェクトをデータベースに挿入するだけAuditableです。

私が抱えている問題は、オブジェクトを永続化するトランザクション中に何らかの例外的な状況が発生した場合に発生しAuditableます。トランザクションはロールバックされますが、それでもAuditTrailレコードが挿入されます。

私はこれを回そうとしました:

StatelessSession session = event.getPersister().getFactory().openStatelessSession();

これに:

Session session = event.getSession();

しかし、そのセッションを使用しようとすると、メッセージで終わるスタック トレースが発生しますSession is closed

問題は、ロールバックにつながる例外的な状況の前に、トランザクションの途中でイベントが発生し、イベント リスナーが独自のセッションを使用する必要があるため、ロールバックされないことです。

イベントリスナーのアクションもロールバックされるようにする方法はありますか? トランザクションの早い段階で発生するイベントを選択しましたか? ロールバックが発生する可能性のある最後のポイントの後に発生するイベントをキャッチして、ロールバックが発生したAuditTrail場合に挿入がトリガーされないようにするイベントはありますか?

4

2 に答える 2

7

誰も答えなかったので、私は自分で調査を続けました。私の最初の解決策は次のとおりです。

public class AuditListener implements PostInsertEventListener {
  private static final long serialVersionUID = -966368101369878522L;

  @Override
  public void onPostInsert(PostInsertEvent event) {
    if (event.getEntity() instanceof Auditable) {
      Session session = null;
      try {
        session = event.getPersister().getFactory().getCurrentSession();
        Auditable auditableEntity = (Auditable)event.getEntity();
        session.save(new AuditTrail(auditableEntity.getClass().getSimpleName(),
            auditableEntity.getId(), auditableEntity.getStatus(),
            auditableEntity.getLastModified()));
      } catch (HibernateException he) {
        System.out.println("Horrible error: " + he.getMessage());
        session.getTransaction().rollback();
      }
    }
  }
}

getCurrentSession()から " " をPostInsertEvent呼び出していることに注意してくださいSessionFactoryImplementor。これが潜在的に危険な戦略であるかどうかはよくわかりません。また、その呼び出しをそのままにしておくことが理にかなっているのかどうかもわかりませんrollback()が、機能しているようで、他の誰もより良い解決策を提供していません. では、どうぞ。

于 2013-01-21T16:22:02.123 に答える