2009-04-04 9 views
2

これは通常クラスをどのように設計するのでしょうか? 1クラス= 1テーブル。 別のテーブルへの外部キーを含むテーブルはどうですか?テーブルデザインに基づいたモデリングクラス

は、私は次のようしていると仮定します。

PersonTable 
--------------- 
person_id 
name 

PersonMapTable 
--------------- 
map_id 
type_id (fk) 
person_id 

PersonTypeTable 
------------------- 
type_id 
description 
parent_type_id 

AddressTable 
------------------- 
address_id 
address1 
address2 
city 
state 
zip 

AddressMapTable 
----------- 
address_map_id 
address_id 
person_id 

良い方法は、各テーブル用のクラスを作成で構成されますか? もしそうなら、そのようなクラスをormなしでデータベースにロード/保存するためのベストプラクティスは何ですか?簡単なコード例が本当に役に立ちます

答えて

10

私はクラスとテーブルの間のマッピングのいくつかのパターンを持っているMartin Fowler氏のPatterns of Enterprise Application Architectureを、読んでお勧めします。

+0

ありがとうございます。私はそれを読むつもりだ! 注意してください。 – zSynopsis

3

テーブルごとに1つのオブジェクトが必ずしも良いデザインだとは思いません。 1つのサイズをすべてのルールに適合させるのは難しいですが、オブジェクトはより豊かで細かい粒度にすることができます。データベースは、オブジェクトに適用されない理由で非正規化することができます。その場合、テーブルよりも多くのオブジェクトがあります。

あなたの場合は、1含まれます:1および1:Mの関係:

public class Person 
{ 
    // 1:m 
    private List<your.namespace.Map> maps; 
} 

public class Map 
{ 
    // 1:1 
    private your.namespace.Type; 
} 
+0

ありがとうございました。 次のようなUIがあるとします: 名前Person_Type_Id、Person_Type。 Person person = new Person(Name、PersonType、PersonTypeId)、PersonコンストラクタにMapオブジェクトを作成させますか? – zSynopsis

+0

UI?私たちは永続性について話していますね。そして "PersonType"?あなたのデザインにはいくつのタイプがありますか?私にとって役割を果たすように聞こえる - そうであれば、あなたが提案しているように私はそれをしないだろう。 – duffymo

+0

TypeTable(Value = id、Text = Type)から生成されたリストボックスを持つユーザーインターフェイスがあります。 5〜10人のタイプがあります(この数字は1日に増えます)。 – zSynopsis

1

を私はあなたが多くの関係に多くを持っている場合は特に、私はいつもテーブルごとにクラスを持っていることを言わないだろう。あなたのテーブルに基づいて、私は2つのクラスを持っているだろう...私はなぜあなたが両方とidとperson_type_idを持っているのかわからない、彼らは同じことだが、ここではクラスです。

Person 
{ 
    public int Id { get; set; } 

    public string Name { get; set; } 

    public List<PersonType> { get; set; } 
} 

PersonType 
{ 
    // I would discourage from using Type as property name as it is a keyword... 
    public string [Type] { get; set; } 
} 
+0

私は間違いでした。ありがとうございました – zSynopsis

+0

ようこそ!ありがとうございました! – bytebender

1

ユーザーがデータ入力担当者でない限り、一般的には使用ケース/ユーザーストーリーからクラスを設計する方が良いと考えられます。データベースが既に存在する場合でも。

理由は?ユーザーが自分の仕事を助けるソフトウェアを期待するのではなく、自分の仕事がソフトウェアを使うことを前提とするのは簡単すぎる。

明らかに、彼らはある時点で交差する必要があります。私はファウラーの本は始めるのに最適な場所だと同意する。しかし、私は彼がこの観点を強化すると思う。

クラスとデータベースの両方を正しく取得できるモデリングパースペクティブが必要な場合は、オブジェクトロールモデリングを検討してください。

2

ほとんどの場合、テーブルをエンティティにマップする傾向がありますが、それは厳しいルールではありません。場合によっては、特定のエンティティのリポジトリが特定のエンティティを取り巻く一般的な問題に対処する方が良い場合があります。つまり、結果的に他のテーブルを扱うことになります。

何か決しては(従属データが常にエンティティで検索される必要がある非常に具体的な計画されたケースを除いて)、エンティティまたはエンティティの集合が別のエンティティのプロパティとして設定されます。代わりに、そのエンティティは、親エンティティのプロパティであるか、または親エンティティに関連して関連するリポジトリを介して検出可能であるそのIDを介して、そのエンティティを検出可能にする。

子エンティティまたは別のエンティティのエンティティをまとめてバンドルする必要がある場合は、必要なすべてのデータをまとめて "info"ヘルパークラスを使用します。たとえば、エンティティクラスWidgetがあり、オブジェクトのコレクションがPartのオブジェクトの場合、Widgetインスタンスをプロパティとして、Partオブジェクトを他のプロパティとして含むWidgetInfoクラスを作成します。

このように、すべてのエンティティクラスはできるだけ軽量のままであり、従属データをロードする必要があるという仮定を決してしません。また、エンティティクラスに子オブジェクトコレクションを作成する場合には、一般的に乱雑なORM領域に入ることなく、リポジトリモデルをきれいに保ちます。 ORMなしで実行すると、子をロードするかどうか、子がロードされているかどうか、ロードされていないかどうかの問題が発生します。

0

オブジェクト・リレーショナル・マッピング(ORM)を使用する予定がある場合、これは表のデザインに影響する可能性があります。たとえば、Hibernateは、同じツリー内の混合継承マッピング戦略が好きではありません。

ORMを使用しないことを具体的に示しているので、従来のデータベース設計プリンシパルに従うことができます。これは通常、クラスごとに1つのテーブルから始め、第3正規形(read about database normalization here)に正規化してから、パフォーマンスの制約(read about denormalization here)を満たすように非正規化することを意味します。

ORMを使用せずにオブジェクトをロードして保存する方法についての質問は、データアクセスオブジェクト(DAOs)を使用することです。

public interface ICustomerDao 
{ 
    public void insert(Customer customer) throws CustomerDaoException; 
    public void update(long id, Customer customer) throws CustomerDaoException; 
    public void delete(long id) throws CustomerDaoException; 
    public Customer[] findAll() throws CustomerDaoException; 
    public Customer findByPrimaryKey(long id) throws CustomerDaoException; 
    public Customer[] findByCompany(int companyId) throws CustomerDaoException; 
} 

あなたが使用している言語を指定していないが、関係なく、あなたが有益なDAOのためthis example using Java genericsを見つけることがあります。ここでは簡単な例です。

0

各テーブルのクラスを作成するのがよいでしょうか? なら、 のクラスのロード/保存のベストプラクティスは ormのないデータベースに戻っていますか?

ORMを使用しています。オブジェクトをリレーショナル表にマッピングしています。これを行うために予めビルドされたライブラリを使用するかどうかは、あなたの呼び出しです。そうしないと、本質的に自分自身を実装することになりますが、おそらく既存のORMのすべての鐘や笛がないでしょう。

これを行う最も一般的な方法は、ActiveRecordパターンとData Mapperパターンです。それぞれには長所と短所があります。

ActiveRecordパターンでは、属性によって表の列を定義するクラスを定義します。このクラスの各インスタンスはデータベースの行に対応し、新しいインスタンスを作成(および保存)するとデータベースに新しい行が作成されます。その詳細については、こちらを参照してください。http://en.wikipedia.org/wiki/Active_record_pattern

データマッパーパターンでは、各テーブルのテーブルオブジェクトを定義し、既存のクラスにテーブルの列を割り当てるマッパー関数を作成します。 SQLAlchemyはデフォルトでこのパターンを使用します(ただし、ActiveRecordタイプの拡張モジュールがあり、SQLAlchemyの機能を別のインターフェイスに適用します)。このパターンの簡単な紹介は、SQLAlchemyのドキュメントのhttp://www.sqlalchemy.org/docs/05/ormtutorial.htmlにあります。セクション「表、クラス、マッパーを一度に宣言的に作成する」を参照してください。このセクションでは、SQLAlchemyを使用したActiveRecordについて説明します)。

ActiveRecordパターンは、設定が簡単で作業が容易で、データベースを明確に表すクラスが用意されているため、可読性の点でメリットがあります。副次的な利点として、ActiveRecordクラスの宣言的性質は、データベーススキーマの明確で分かりやすいドキュメントとして効果的に機能します。

データマッパーパターンを使用すると、データがクラスにどのようにマッピングされるかを柔軟に設定できるため、テーブルとクラスの一対一の関係に縛られることはありません。また、永続性レイヤーをビジネスコードから分離するので、必要に応じて他の永続性メカニズムを後で交換することができます。また、データベースをバックアップする必要がなくても、クラスのテストを簡単に行うことができます。

SQLAlchemyのマッパー設定の詳細については、http://www.sqlalchemy.org/docs/05/mappers.htmlを参照してください。 SQLAlchemyのようなライブラリの使用を計画していない場合でも、ドキュメントは、クラスをデータベーステーブルにマッピングする際に考慮する必要があるオプションの一部を表示するのに役立ちます。

0

このクラスの視点から見たこのデータベースは、多くのコードをすばやくクランキングすることにつながります。しかし、このコードの良い塊は、おそらく使用されていないか、または重大な突然変異を必要とします。言い換えれば、ディスプレイとワークフローが一致しない特定のクラスを作成する可能性があります。

まず、アプリ、ユーザーのニーズ、一般的なワークフローなどを考えてみましょう。実際には動作可能なように見えます(ディスプレイをモックするなど)。

ディスプレイを使用して、必要に応じてストレージ(dbデザイン)をモデル化するために必要なクラスに集中します。ほとんどのクラスでは自然にディスプレイ用のソリューションを提供する傾向があるため、ストレートテーブルクラスはごくわずかです。

幸運。