2

JPA 2.0、JSF 2.0、EJB 3.1 などを含む JEE6 スタックを使用しています。

私のアーキテクチャのセットアップ方法は次のとおりです。

JPAプロバイダーとしてhibernateを使用して、JPAアノテーション付きDAOを持っています。facelet/xhtml ページに対応する JSF Managed Bean があります。すべてのデータベース要求を処理する EJB があります。

私の XHTML ページには、マネージド Bean を呼び出す JSF EL があります。マネージド Bean には、EJB によって管理される DAO エンティティへの参照が含まれています。たとえば、db テーブルにマップされたユーザー エンティティがあります。ユーザーを返すすべての CRUD 操作を処理するユーザー EJB があります。ユーザーを編集するページがあります。高レベルのワークフローは次のようになります: ユーザー編集ページに移動 -> EL は、ユーザーをロードするマネージド Bean にあるメソッドを呼び出します。このメソッドは、EJB から userEJB.loadUser(user) を呼び出して、データベースからユーザーを取得します。ユーザーが編集されて送信されます -> マネージド Bean で関数が呼び出され、EJB で関数が呼び出されてユーザーが保存されます。等

EJB を使用して JSF ページ内のデータにアクセスする際に問題が発生しています。遅延初期化エラーで多くの問題が発生しています。これは、セットアップ方法が原因であると考えています。

たとえば、遅延ロードされるユーザーのリストを持つ Client エンティティがあります。クライアントを取得するために、EJB でメソッドを呼び出します。このメソッドはデータベースにアクセスし、クライアントを見つけて返します。後で、このクライアントのユーザー リストにアクセスしたいのですが、そのためには、何らかのメソッドを呼び出して EJB に戻り、それらのユーザーをロードする必要があります (ユーザーは遅延ロードされるため)。これは、次のようなメソッドを作成する必要があることを意味します

public List<User> getUserListByClient(Client c)
{
    c = em.merge(c); return c.getUserList();
}

このメソッドの唯一の目的は、ユーザーをロードすることです (そして、このアプローチが優れているか、機能するかについては確信が持てません)。私が自分でセッション管理を行っていた場合、リクエスト全体に対してセッションを開いたままにして、プロパティに直接アクセスしたいのですが、とにかくセッションが開いているので問題ありません.EJBには間接的なレイヤーが1つあるようです.それは私にとって物事を困難にしています。

コンテナーによって制御され、プールされ、無料でトランザクション管理を提供するなどの点で、EJB が好きです。しかし、EJB を正しく使用していないか、JSF アプリを正しく設定していないような気がします。

どんなフィードバックでも大歓迎です。

ありがとう、

4

2 に答える 2

2

自分でセッション管理を行っている場合は、リクエスト全体に対してセッションを開いたままにして、プロパティに直接アクセスしたいのですが、とにかくセッションが開いているので、これで問題ありません。

実際、これはビューパターンで開いているセッションです(ビューで開いているEntityManagerとも呼ばれます)。EJBでも使用できます。理想的には、トランザクションはビジネスレイヤー/ EJBで管理する必要があります。これにより、純粋なレイヤーアーキテクチャからのわずかな逸脱が見られます。ただし、ビューでの遅延読み込みの問題は解決され、簡単です。

それ以外の場合は、トランザクションの終了後に使用される情報を熱心にロードする必要があります。または、DTOに依存することもできますが、それでは面倒になり始めます。

このトピックをカバーし、賛否両論と代替案について説明しているリンクがさらに2つあります。

于 2010-04-22T18:45:33.373 に答える
1

あなたの使い方は良さそうです。em.merge(c) は、クライアント c に加えられた変更をデータベースに保存する場合があることを覚えておいてください。クライアント c に加えられた変更を保存せずに、クライアント c の UserList を取得するだけの場合は、次のようにします。

public List<User> getUserListByClient(Client c)
{

     Client client = em.find(Client.class, c.clientId);
     return client.getUserList();

}

または、完全な Client オブジェクトを渡す代わりに、Client Id を getUserListByClient に送信するだけで、わずかなメモリを節約できます:)

于 2010-04-24T14:43:32.623 に答える