2012-03-31 7 views
12

DAOオブジェクトを使用して永続化するエンティティが2つあるとしましょう。私たちは、だから私はJPAにJDBCから永続性の実装を切り替えることができるようにしたい場合はDAOデザインパターン

class JdbcUserDao implements UserDao{ 
//... 
} 

class JdbcAddressDao implements AddressDao{ 
//... 
} 

で終わるので、だから我々は、右のインターフェイスを実装し、その逆(例えば)、私はJPAUserDaoとJPAAddressDaoを持っている必要があるだろう...私は20のエンティティを持っていて、(DIコンテナを使用して)実装を切り替えることにした場合、コード内でJPAを使ってすべてのJdbc実装を切り替える必要があります。今

それは私がDAOがどのように動作するか誤解いるかもしれませんが...私はちょうど

class JdbcDaoImpl implements UserDao,AddressDao{ 
//... 
} 

が、私はその後、1クラス内のすべてのJDBCの実装を持っているのだがあった場合、およびスイッチング実装は作品だろうケーキのまた、DaoImpl数はDaoインターフェースの数に等しい。なぜ実装(jdbc、JTA、JPA ...)によってそれらをグループ化し、1つのクラスの下にすべてを持っていないのですか?

ありがとうございます。

+3

あなたは一つの大きな 'メイン()'メソッドにアプリケーションをコーディングしない理由と同じ理由:関心事の分離。 (誰もあなたが普通のコードを含む抽象的な 'JdbcDaoBase'をコード化し、あなたの' Dao'でそれを拡張するのを防ぎません) – rsp

+0

100クラスより1クラスで500メソッドを置き換える方が簡単なのはなぜですか? –

答えて

20

アプリケーション全体ですべてのDAOインターフェイスを実装する単一のクラスを実装することは、どちらかというと悪い設計になります。

より多くの典型的なパターンは、これらのベースクラスは、発見/取得/リードのようなメソッドが含まれている/店舗/存続を保存し、更新/修正するなどJDBCBaseDAO、(もしばしばGenericDAO呼ばれる)BaseDAOインタフェースを持っているとJPABaseDAOを持つことです削除/削除/パージを行います。 UserDAO

特定DAOインターフェイスは、次いで、BaseDAOから継承しJPAUserDAO等具体的な実装は、JPABaseDAOから延びています。

BaseDAOインタフェースは次のようになります。

public interface BaseDAO <T> {  
    T getByID(Long ID); 
    T save(T type); 
    T update(T type); 
    void delete(T type); 
} 

そしてUserDAOインタフェース:このインタフェースを実装するJPABaseDAO

public interface UserDAO extends BaseDAO<User> { 
    List<User> getAllAuthorized(); 
} 

ベア骨例:

@Stateless 
public class JPABaseDAO<T> implements BaseDAO<T> { 

    @PersistenceContext 
    private EntityManager entityManager; 

    private final Class<T> entityType; 

    @SuppressWarnings("unchecked") 
    public JPABaseDAO() { 
     this.entityType = ((Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0]); 
    } 

    @Override 
    public T getByID(Long ID) { 
     return entityManager.find(entityType, ID); 
    } 

    @Override 
    public T save(T type) { 
     return entityManager.persist(type);   
    } 

    @Override 
    public T update(T type) {   
     return entityManager.merge(type); 
    } 

    @Override 
    public void delete(T type) { 
     entityManager.remove(entityManager.contains(type) ? type : entityManager.merge(type)); 
    } 

} 

そして、いくつかのサンプルUserDAOそれから継承する実装:実際には

@Stateless 
public class JPAUserDAO extends JPABaseDAO<User> implements UserDAO { 

    @PersistenceContext 
    private EntityManager entityManager; 

    @Override 
    public List<User> getAllAuthorized() { 
     return entityManager.createNamedQuery("User.getAllAuthorized", User.class) 
          .getResultList(); 
    } 
} 

基底クラスは、多くの場合、インスタンスは、エンティティがAuditableインターフェースのいくつかの種類を実装している場合のチェック、およびそれを自動的に変更された日付とユーザーを設定するために、透過的に他のいくつかのことを行うことができます

EJBを使用してDAOを実装する場合、実装を変更する1つの戦略は、すべてのJDBC実装を1つのパッケージに入れ、すべてのJPA実装をもう1つのパッケージに入れることです。次に、ビルドには1つの実装パッケージのみを含めます。

+0

優秀、ありがとうございました。複数のテーブルを含むCRUD操作はどうでしょうか?例えば、私はオブジェクトを取得するためにselect文を実行し、それを使って別のDAO implのCRUDを呼び出したり、ある種のalien hybrid DAOを作成したりすることはできますか? Btw。あなたは私に大きな助けになりました。とても感謝しています。 – Mercurial

+1

複数のエンティティ/テーブルを含むCRUDや操作は、しばしば複数のDAOを集約するサービスによって処理されます。 EJBでは、複数のDAOを呼び出しても(伝播する場合でも)同じ永続コンテキスト内に自動的に移動します。もう1つの可能性は、エンティティが関連付けられている(User has-a House)場合、ユーザー用のDAOのみが必要であり、JPAはUserオブジェクトから自動的に家を取得/保存/更新するということです。 –

+1

いいですね。このアプローチは、さまざまなプロジェクトで私が従ったアプローチです。それは非常によく安定して動作することが証明されました。私はそれをここで詳しく説明します:http://codeblock.engio.net/?p=180 – bennidi

1

依存性注入の全体のポイントは、実装の切り替えを簡単にし、ユーザーをプロバイダから切り離すことです。したがって、すべてのDIフレームワークは、いくつかの実装(ここではJDBCグループとJPAグループ)を「グループ化」し、それらを1か所で切り替えるための方法を提供します。

また、通常、消費者の数(あなたのケースでは、ユーザーと住所を扱ういくつかのビジネスロジック)は、DAフレームワークのDAOの数よりも通常多くなります。仮定:50のビジネスビーン、2つのインターフェイスと2つのインプリメンテーション(各4つ):基本的なDIでも50の世話をします。

+0

「その他」の部分について教えてください。どうもありがとう。 – Mercurial

+0

@ user1304844:私はしたいですが、私は不明なものがわからない。 –

+0

"でも、基本的なDIは50の世話をします。グループ化を使うと残りの半分が残ります。" - 私はこれを理解していない。 – Mercurial

0

持続性テクノロジの切り替えや複数のテクノロジの混在さえも実現できるように、テクノロジに依存しない方法でDAOパターンを実装する可能性は間違いありません。この記事では、githubのソースコードを含む1つの実装体系を紹介します。

http://codeblock.engio.net/?p=180