0

クライアントからのリモート呼び出しを受け入れるRMIクラスがあります。

このクラスは、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();
}

すべてのメソッドでコーディングしなくても、この「セッションを開く/休止状態の例外をキャッチする/休止状態のリソースを最後に閉じる」動作を自動的に実行するために(比較的簡単に)実装できるパターンがあるかどうかを知りたいです。

Webアプリケーションで使用される「ビューでセッションを開く」に似ていますが、HTTPリクエストの代わりにremotrRMIメソッド呼び出しに適用できます。

理想的には、メソッド名を文字列として渡す反射を使用せずに、メソッドを直接呼び出すことができるようにしたいと思います。

4

2 に答える 2

0

spring+hibernateスタックを使用することをお勧めします。これにより、あなたが探していると思う繰り返し可能なコードをたくさん節約できます。このリンクを確認してください。これは実際にはWebアプリケーションの例ですが、スタンドアロンアプリケーションにも同じように使用できます。

于 2012-05-09T15:00:06.573 に答える
0

私が欲しかったのは、可能であれば「迅速でクリーンな」ソリューションだったので、今のところ新しいフレームワークはありません(ただし、後でSpring + Hibernateスタックを使用する可能性があります)。

そのため、「Command」パターンのバリアントを含む「迅速で汚くない」ソリューションを使用することになりました。このソリューションでは、休止状態の呼び出しが、汎用Commandインターフェイスを実装する匿名の内部クラス内にカプセル化され、コマンド実行機能がHibernateセッションと例外処理を使用して呼び出します。ジェネリックビットは、executeメソッドの戻り値のタイプを変えるためのものです。

このソリューションには100%満足していません。これは、ビジネスロジックにボイラープレートコードがラップされていることを意味し(戻り値に必要な明示的なキャストに特に不満があります)、理解とデバッグが少し複雑になるためです。

ただし、反復コードの増加は依然として重要であり(メソッドあたり約10行から3〜4行)、さらに重要なことに、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メソッドにパラメーターとして渡すことができます。

于 2012-05-10T13:37:48.940 に答える