web-dev-qa-db-ja.com

JSFコントローラー、サービス、およびDAO

データへのアクセスに関してJSFがどのように機能するかに慣れようとしています(春の背景から来ています)

私はユーザーのリストを維持する簡単な例を作成しています、私は次のようなものを持っています

<h:dataTable value="#{userListController.userList}" var="u">
    <h:column>#{u.userId}</h:column>
    <h:column>#{u.userName}</h:column>
</h:dataTable>

次に、「コントローラー」には次のようなものがあります

@Named(value = "userListController")
@SessionScoped
public class UserListController {
    @EJB
    private UserListService userListService;

    private List<User> userList;

    public List<User> getUserList() {
        userList = userListService.getUsers();
        return userList;
    }
}

そして、「サービス」(DAOのように思えますが)

public class UserListService {

    @PersistenceContext
    private EntityManager em;

    public List<User> getUsers() {
        Query query = em.createQuery("SELECT u from User as u");
        return query.getResultList();
    }
}

これは物事を行う正しい方法ですか?私の用語は正しいですか? 「サービス」はよりDAOのように感じますか?そしてコントローラーは、サービスの仕事の一部を行っているように感じます。

32
PDStat

これは正しいやり方ですか?

マネージドBeanゲッターメソッドで非効率的な方法でビジネスロジックを実行し、マネージドBeanスコープが広すぎるとは別に、大丈夫そうです。サービス呼び出しをgetterメソッドから@PostConstructメソッドに移動し、@RequestScopedの代わりに@ViewScopedまたは@SessionScopedのいずれかを使用すると、見栄えが良くなります。

こちらもご覧ください:


私の用語は正しいですか?

いいんだよ。一貫性があり、コードが理にかなった方法で読み取り可能である限り。クラスと変数の命名方法は、やや厄介です(非論理的および/または重複)。たとえば、個人的にはusersの代わりにuserListを使用し、var="user"の代わりにvar="u"を使用し、代わりにidnameを使用しますuserIdおよびuserName。また、「UserListService」は、一般的なユーザーではなくユーザーのリストのみを処理できるように聞こえます。 「UserService」を使用したいので、ユーザーの作成、更新、削除にも使用できます。

こちらもご覧ください:


「サービス」はよりDAOのように感じますか?

まさにDAOではありません。基本的に、JPAは本物のDAOです。以前は、JPAが存在しなかった場合、すべてのユーザーがDAOインターフェイスを自作しているため、基礎となる実装(「プレーンオールド」JDBC、「グッドオールド」Hibernateなど)が変更されてもサービスメソッドはそれらを使用し続けることができます。サービスメソッドの実際のタスクは、トランザクションを透過的に管理することです。これはDAOの責任ではありません。

こちらもご覧ください:


そしてコントローラーは、サービスの一部の仕事をしているように感じます。

この比較的単純なセットアップでそれを行うと想像できます。ただし、実際にはコントローラーはバックエンドではなくフロントエンドの一部です。このサービスはバックエンドの一部であり、JSF、JAX-RS、「プレーン」JSP + Servlet、Swingなど、すべての異なるフロントエンドで再利用できるように設計する必要があります。さらに、フロントエンド固有のコントローラー( 「バッキングBean」または「プレゼンター」とも呼ばれます)、フロントエンド固有の方法で成功および/または例外的な結果を処理できます。たとえば、サービスからスローされた例外の場合にJSFがfaceメッセージを表示する場合です。

こちらもご覧ください:


全体として、正しいアプローチは次のようになります。

<h:dataTable value="#{userBacking.users}" var="user">
    <h:column>#{user.id}</h:column>
    <h:column>#{user.name}</h:column>
</h:dataTable>
@Named
@RequestScoped // Use @ViewScoped once you bring in ajax (e.g. CRUD)
public class UserBacking {

    private List<User> users;

    @EJB
    private UserService userService;

    @PostConstruct
    public void init() {
        users = userService.listAll();
    }

    public List<User> getUsers() {
        return users;
    }

}
@Stateless
public class UserService {

    @PersistenceContext
    private EntityManager em;

    public List<User> listAll() {
        return em.createQuery("SELECT u FROM User u", User.class).getResultList();
    }

}

正規のJava EE/JSF/CDI/EJB/JPAプラクティス: Java EEキックオフアプリ を使用して、実際のキックオフプロジェクトを見つけることができます。

こちらもご覧ください:

67
BalusC

これはdaoです 実際にはリポジトリ ですが、永続コンテキストを使用してデータベースにアクセスしているので、その違いについてあまり心配しないでください。

そのメソッドをラップし、トランザクションが呼び出されるサービスクラスを作成する必要があります。

サービスクラスが不要であると感じることもありますが、多くのdaoメソッドを呼び出すサービスメソッドがある場合は、その使用がより保証されます。

私は通常、パターンが同じままであり、daoが直接注入されないようにするために、それが不要だと感じても、サービスを作成するだけです。

これにより、追加の抽象化レイヤーが追加され、将来のリファクタリングがより柔軟になります。

6
NimChimpsky