2011-12-22 18 views
2

私のJavaアプリケーションでは、データベース操作の抽象化レイヤーを実装したいと思います。私はアプリケーションを任意の種類のデータベースにバインドしたくない(SQL、XML、文書ベース、醜いテキストファイルの束など)。DAOの設計とデータ構造

エンティティ間には多くの関係がありますが、時間のうち、関係は1対多である。

更新と免責事項:例はシンプルですが、ORM/SQLモデルに適合しない本当のチャンスを持つより複雑なモデル全体の一部に過ぎません。関係の中に正規化されたとき、およびデータの性質の変化のために10億のレコード)。ここで私は簡単な関係を実装することを求めていますが、実際にアプリケーションの唯一の問題であるとは限りません。

簡単な例は以下の通りである:

public class Vehicle { 
    String mark; 
    String model; 
    String registrationId; 
} 

public class Depot { 
    String name; 
    String address; 
} 

これらのエンティティのそれぞれは、独自のDAOインタフェースを有する:

public interface VehicleDAO { 
    List<Vehicle> getVehicles(); 
    Vehicle getVehicleByRegistrationId(String registrationId); 
} 

public interface DepotDAO { 
    List<Depot> getDepots(); 
    Depot getDepotByName(String name); 
} 

これらのDAOはわずかに分離されているいくつかの方法を示すために、同様に簡略化されます特定のエンティティ(登録IDで車両を取得するために、他のエンティティについては何も知る必要はありません)。

そして今興味深い部分が来ます。 デポと車両の関係は1対多です。ですから私はエンティティクラスとDAOメソッドの両方でこの関係を実装する必要があります。

  • 場所List<Vehicle>プロパティクラスDepot内側と私は(可能怠惰なフェッチ改善に)Depotインスタンスを取得するたびに、それを移入:

    は、今のところ私はこのために2つのアプローチがあります。この方法でDAOインターフェイスは変更されません。

  • DepotVehicleの特別な識別子を導入し、エンティティクラスは追加の整数プロパティint id;を取得し、DAO List<Vehicle> getVehiclesForDepot(int depotId)にメソッドを追加します。このアプローチは、単純な整数の代わりに識別子のための特別なクラスを導入することによって強化することができます。

他の方法がありますか?エンティティとデザインの関係をモデル化する最良の方法は何ですか?DAOインターフェイスを使用すると、データベースの抽象化は使いやすく、どのタイプのデータベースにもバインドされません。私は必ずしも完全で正確な解決策を求めるのではなく、むしろ上記の問題を解決する際のいくつかの原則について尋ねています。あなたは一貫idを使用する場合はDAOのタイプにローカライズされているメソッドを使用し、あなたの例では

+6

これはホイールの再発明と呼ばれ、HibernateのようなORMを使用します。 –

+0

@PetarMinchevはORMを使用して、データベースの種類にバインドされていない要件の1つに違反しています –

+2

次に、ORMをデータベース部分のみに使用します。また、実際のプロジェクトでは、データ記憶域をデータベースから「xml」などに変更することはまだありません。 –

答えて

1

は、などすなわち、これらの機能をカバーするためにDAOのメソッドの一貫性のあるセットを定義するために

// load object of DAO type T 
<T> load(id) 
// load objects of DAO type T 
List<T> load(List<id>) 
// load all objects of DAO type T 
List<T> find() 
// load multiple objects of DAO type T 
List<T> find(relation) 

優れていますタイプ(longなど)では、基本メソッドをカバーするinterfaceを定義することができます。List<T>データホルダーの属性を作成し、load()の一部としてそれを埋める

  • :あなたは最高のは、オブジェクトの使用状況とそれらの関係に依存しているいくつかのオプションを持っている関係をロードするために

これは、関係するエンティティが他のエンティティとの関係を持たない場合に、少量の関係に有効です。彼らが行う場合は、部分的にフロントまであまりロードを防ぐためにそれらをロードする必要があります(あなたが述べたように、遅延ロードを戦略です。)

  • List<T_id>データホルダーの属性を作成し、load()の一部としてそれを埋めます

これは、関連するエンティティにアクセスするためのload(List<id>)メソッドと一緒に使用される適度な関係で機能します。以下のような大量のデータについては

、あなたが言及として、あなたが解決しようとしている問題の大部分である、あなたは少しさらに関係を切り離すことができ、使用DAO方法:

// retrieve related entity id's for this DAO T 
List<id> loadIds(T) 

ロードします引数として渡されたデータ保持オブジェクトとの関係を持つエンティティの(外国の)idのセットです。あなたのマネージャー/ビジネス/サービス層は、idリストにオフセットを渡し、ロードするエンティティの量をチャンクして、次のエンティティのセットをロードするためにそのidのリストを使用します。

また別のDAOのタイプのデータ・ホルダー・オブジェクト内の外交関係を埋めるためにDAOのメソッドを追加することにより、関係に関する知識を切り離すことができます。

// fill entity relations for T2 to this DAO tyoe T 
void fill(T2) 

T::fill()方法を取得するにはT2にゲッターを使用しますロードする関連エンティティ(またはそれらのid ')を決定するために必要なデータ、およびその情報をT2データホルダオブジェクトに格納する1つまたは複数のセッタ。

これらのほとんどのDAOのロードメソッドでは、リレーショナルデータをnullに設定したままにしておくと、後でロードできます。これはもちろん、データ保持オブジェクトgetterがnullの値を契約の一部として処理できる必要があることを意味します。

+0

ありがとう!ジェネリックに関しては、インタフェースの観点からは有用であるかもしれませんが、特定の実装になると、メソッドは非常に大規模になります。これは、異なるエンティティが異なるプロパティを持つためです。実際の実装に 'if(T instanceof X)'というチェックがあふれないでしょうか? –

+0

現在、私は第2のアプローチ(関係を維持するためにidのリストを使用する)が最良の方法だと思います。大量のデータは、エンティティの一部の小さなサブセット(車両の操作データ - 私は少し別の戦略を使用することができます)のためだけに、私はむしろデザインをよりクリーンにするソリューションに固執したいと思います。 –

+0

@pavel_kazlou、ジェネリックをあまり使わないことは正しいですね。あなたのデータモデルがサポートしているのであれば、 'long'、' String'、 'List'とあなたのDAOデータ保持者型だけを引数として持つ、非ジェネリックなインターフェースだけを使用してください。読み込まれたリストがDAOメソッドを変更しない場合は、 'List'の代わりにidとdata-holderオブジェクトがあれば配列を返すことができます。 (膨大な量のデータを処理しているときにメモリが問題になっている場合) – rsp

関連する問題