2012-05-09 3 views
0

クライアントからのリモート呼び出しを受け付けるRMIクラスがあります。RMIリモートメソッドでHibernateボイラープレートを自動化する方法

このクラスは、Hibernateを使用してエンティティをロードし、ビジネスロジックを実行します。通常は読み取り専用です。リモートメソッドの体のほとんどがそのように見える

現在:

try { 
    HibernateUtil.currentSession().beginTransaction(); 

    //load entities, do some business logic... 

} catch (HibernateException e) { 
    logger.error("Hibernate problem...", e); 
    throw e; 
} catch (other exceptions...) { 
    logger.error("other problem happened...", e); 
    throw e; 
} finally { 
    HibernateUtil.currentSession().getTransaction().rollback(); //this because it's read-only, we make sure we don't commit anything 
    HibernateUtil.currentSession().close(); 
} 

私は(比較的簡単に)自動的に、これは「開こうとするために実装することができ、いくつかのパターンがあるかどうかを知りたいですセッション/すべてのメソッドでコード化することなく、Hibernate Exception/catch Hibernate resources "ビヘイビアをキャッチします。

webappsで使用されているが、HTTP要求の代わりにremotr RMIメソッド呼び出しに適用できる "open session in view"と同様のものです。

理想的には、メソッドを直接呼び出すことができますが、リフレクション渡しのメソッド名を文字列として使用しないことが理想です。

答えて

0

私が欲しかったのは、できるだけ早くクリーンなソリューションでしたので、今は新しいフレームワークがありません(後でSpring + Hibernateスタックを使用するかもしれません)。

私は、 "Command"パターンの変種を含む "クイック・アンド・ノット・ソー・ダーティ"のソリューションを使用しました。ここで、ハイバーネーション・コールは、汎用コマンド・インターフェースを実装する匿名の内部クラスの中にカプセル化されています。コマンド実行者は、Hibernateセッションと例外処理で呼び出しをラップします。ジェネリックビットは、executeメソッドの戻り値の型が異なるためです。

私はこのソリューションに満足しているわけではありません。これは、ビジネスロジックを包み込んでいる定型的なコードを意味しています(私は戻り値に必要な明示的なキャストに関して特に不満です)。デバッグ。

しかし、繰り返しコードの利得はまだかなり(1行あたり約10行から3行まで)重要であり、さらに重要なことに、Hibernateの処理ロジックは1つのクラスに集中しているため、必要に応じて簡単に変更できます。エラーが起こりにくい。

コマンドインタフェース:

public interface HibernateCommand<T> { 
    public T execute(Object... args) throws Exception; 
} 

実行手段:ここ

は、コードの一部である

public class HibernateCommandExecuter { 

    private static final Logger logger = Logger.getLogger(HibernateCommandExecuter.class); 

    public static Object executeCommand(HibernateCommand<?> command, boolean commit, Object... args) throws RemoteException{ 
     try { 
      HibernateUtil.currentSession().beginTransaction(); 

      return command.execute(args); 

     } catch (HibernateException e) { 
      logger.error("Hibernate problem : ", e); 
      throw new RemoteException(e.getMessage()); 
     }catch(Exception e){ 
      throw new RemoteException(e.getMessage(), e); 
     } 
     finally { 
      try{ 
       if(commit){ 
        HibernateUtil.currentSession().getTransaction().commit(); 
       }else{ 
        HibernateUtil.currentSession().getTransaction().rollback(); 
       } 
       HibernateUtil.currentSession().close(); 
      }catch(HibernateException e){ 
       logger.error("Error while trying to clean up Hibernate context :", e); 
      } 
     } 
    } 
} 

リモートと呼ばれる方法でサンプルの使用(それは、局所的に使用することができます):

@Override 
    public AbstractTicketingClientDTO doSomethingRemotely(final Client client) throws RemoteException { 
     return (MyDTO) HibernateCommandExecuter.executeCommand(new HibernateCommand<MyDTO>() { 
      public AbstractTicketingClientDTO execute(Object...args) throws Exception{ 
       MyDTO dto = someService.someBusinessmethod(client); 
       return dto; 
      } 
     },false); 
    } 

クライアント引数がfinal宣言されているので、内部クラスの内部で参照できるように注意してください。 finalを宣言できない場合、executeCommandメソッドにパラメータとして渡すことができます。

0

spring + hibernateスタックを使用することをお勧めします。これは、私があなたが探していると推測する多くの繰り返し可能なコードを私たちに保存します。 this linkを確認してください。実際にはWebアプリケーションの例ですが、同じものをstandalone applicationでも使用できます。

+0

おかげさまで、Springが助けてくれるかもしれないことを知りましたが、最終的にはプロジェクトに導入する予定ですが、この段階ではオプションではありません。 –

関連する問題