10

私は、通常は CRUD メソッドで始まる、JDBC ベースの古い DAO コードを数多く見てきました。私の質問は、特に検索方法、または「ファインダー」に関連しています。通常、DAO は次の 2 つの方法で開始されます。

  • すべてを見つけて返す
  • 一意の識別子に基づいて特定のインスタンスを取得する

多くの場合、これら 2 つのファインダーでは不十分です。私は通常、次のようなファインダ メソッドを追加するために DAO クラスが繰り返し変更されているのを目にすることになります。

  • ALL where {condition} を検索して返す

新しい {condition} をサポートする必要がある場合、または既存のメソッドを変更して新しいパラメータをフラグとして追加し、メソッド内の SQL クエリを変更して追加の条件をサポートする場合に、さらにメソッドが追加されます。

これは醜いアプローチであり、Open-Closed Principle に違反しています。新しい検索条件をサポートする必要があるたびに、DAO クラスが継続的に変更されるのを目にするのは、私にとって常に気になることでした。この質問に関する調査は、多くの場合、Repository パターンと、検索の条件を仕様またはクエリ オブジェクトとしてカプセル化し、それらをファインダー メソッドに渡すことを示しています。ただし、これは、データセット全体のメモリ内コレクションがある場合、または何らかの ORM を使用している場合にのみ実行可能と思われます (私は古い JDBC コードを使用しています)。

私は、DAO がメモリ内のコレクションとして管理するデータ セット全体を遅延ロードし、仕様パターンを検索用のクエリとして使用するソリューションを検討しました。次に、creates、updates、または deletes メソッドが呼び出されたときにデータベースを更新する、ある種のオブザーバーをコレクションに実装します。しかし、明らかにパフォーマンスとスケーラビリティが大幅に低下します。

これについて何か考えはありますか?


これまでの回答に感謝します。コマンド/ポリシー パターンを使用してデータ アクセス リクエストをカプセル化することについて、どう思いますか? 個々の具象コマンドは、特定の種類のアクセスを表すことができ、Invoker に渡すことができます。最終的に多数の具象コマンド クラスが作成されることになりますが、各クラスは 1 種類のアクセスのみに焦点を当てており、非常にテスト可能で分離されている必要があります。

    public abstract class Command<R>{
       public <R> execute();
       public void setArguments(CommandArguments args){
          //store arguments  
       }
    }

    //map based structure for storing and returning arguments
    public class CommandArguments{
         public String getAsString(String key);
         public String getAsInt(String key);
         //... others
    }

    //In some business class...
    Command command = CommandFactory.create("SearchByName");
    CommandArguments args = new CommandArguments();
    args.setValue("name", name);
    // others
    command.setArguments(args);
    List<Customer> list  = command.execute();
4

2 に答える 2

4

データレイヤーORMにiBatisを使用し、パラメーターとして使用する可能性のあるさまざまなフィールドを持つパラメーターオブジェクトを渡すことで、1つのクエリで提案しているものを実装することができました。

次に、WHERE句で、各フィールドを条件句として指定できますが、パラメータオブジェクトに入力されている場合に限ります。param objの1つのフィールドのみがnullでない場合、結果のフィルタリングに使用されるのはそのフィールドのみです。

したがって、パラメータにフィールドを追加する必要がある場合は、SQLとparamObjを変更するだけです。次に、渡されたパラメーターの組み合わせに基づいてALLまたはサブセットを返す2つのメソッドを使用できます。または、少なくともこのアプローチにより、必要なクエリの数を減らすことができます。

例:の線に沿った何か...

SELECT * FROM MY_TABLE
WHERE FIELD_ZERO = paramObj.field0
<isNotNull property="paramObj.field1">AND FIELD_ONE = paramObj.field1</isNotNull>
<isNotNull property="paramObj.field2">AND FIELD_TWO = paramObj.field2</isNotNull>
<isNotNull property="paramObj.field3">AND FIELD_THREE = paramObj.field3</isNotNull>
于 2011-02-18T03:47:19.023 に答える
0

可能性のある条件が明らかになるたびに特定のファインダー メソッドを作成する代わりに、ジェネリック ファインダー API を作成してみませんか? これは、フィールドを表す内部 Enum を持つ DAO の形式と、DAO のどのフィールドをフィルター処理するか、どのフィルターを適用するかを表すフィールドを持つ DAO の内部クラスのインスタンスのリストを取得するメソッドの形式を取ることができます。およびどのような条件 (AND、OR など)。

セットアップは少し手間がかかり、小さなプロジェクトではやり過ぎかもしれませんが、確かに実行可能です。通常、ORM フレームワークには同様の機能が既に組み込まれているため、そのうちの 1 つを採用することを検討してください (または、レガシー アプリケーションにレトロフィットする独自のソリューションを設計する際に、それらのフレームワークがどのように実装されているかを少なくとも確認してください)。

于 2011-02-17T08:29:12.277 に答える