2


3

これは通常どのようにクラスを設計するのでしょうか。 1クラス= 1表 他のテーブルへの外部キーを含むテーブルはどうでしょうか。

次のようにします。

PersonTable --------------- person_idの名前

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

PersonTypeTable ------------------- type_idの説明parent_type_id

AddressTable ------------------- address_id address1 address2都市状態zip

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

各テーブルにクラスを作成するのがよい習慣でしょうか。 もしそうなら、ormなしでデータベースにそのようなクラスをロード/保存するためのベストプラクティスは何ですか? 簡単なコード例は本当に役に立つでしょう

8 Answer


10


Martin Fowlerの Enterprise Application Architectureのパターンを読むことをお勧めします。これには、クラスとテーブル間のマッピングのパターンがいくつかあります。


3


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

あなたのケースは1:1と1:mの関係を含みます:

パブリッククラスPerson {// 1:m privateリストマップ。 }

パブリッククラスMap {// 1:1 private your.namespace.Type; }


2


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

私がしたことがないこと(依存データが常にエンティティと一緒に取得される必要がある非常に特別な計画の場合を除く)は、エンティティまたはエンティティの集合を別のエンティティのプロパティとして設定することです。 代わりに、そのエンティティは、そのIDを介して発見可能であり、それは親エンティティの財産であるか、または親エンティティに関して関連するリポジトリを介して発見可能である。

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

このようにして、すべてのエンティティクラスは可能な限り軽量のままであり、依存データをロードする必要があるとは想定していません。 また、エンティティクラスに子オブジェクトのコレクションを作成する場合によく見られるような、面倒なORM領域に強制することなくリポジトリモデルをクリーンに保ちます。 ORMなしでそれを実行すると、子をロードするかどうか、および子がロードされたかどうかを想定することが厄介な問題になります。


1


私はいつもテーブルごとのクラスを持っているとは言いません、特にあなたが多対多の関係を持っているとき。 上のあなたのテーブルに基づいて、私は2つのクラスがあるでしょう…​ なぜあなたがidとperson_type_idの両方を持っているのか私にはわかりませんが、それらは同じものですが、ここにクラスがあります。

Person {public int Id {get;};セット; }

パブリック文字列Name {get;セット; }

公開リスト{get;セット; }}

PersonType {//これはキーワードなので、Typeをプロパティ名として使用することはお勧めしません。 公開文字列[型] {取得;セット; }}


1


ユーザーがデータ入力担当者でない限り、一般的にはユースケース/ユーザーストーリーからクラスを設計することをお勧めします。 データベースがすでに存在していても。

理由? ユーザーが自分の仕事をするのを手助けするようにソフトウェアを期待するのではなく、自分の仕事がソフトウェアを行使することであると想定することは結局のところ簡単です。

明らかに彼らはある時点で交差する必要があります。 Fowlerの本は最初から始めるのに最適な場所だと私は同意します。 しかし、私は彼がこの見方を強化すると思います。

クラスとデータベースの両方を正しく理解するのに役立つモデリングの観点が必要な場合は、オブジェクトロールモデリングを検討してください。


0


オブジェクトリレーショナルマッピング(ORM)を使用する予定の場合は、これがテーブルデザインに影響を与える可能性があります。 たとえば、http://www.hibernate.org [Hibernate]は、同じツリー内での混合継承マッピング戦略を好まない。

ORMを使用しないことを明確に示したので、従来のデータベース設計原則に従うことができます。 これは通常、クラスごとに1つのテーブルから始めて3次正規形に正規化し( ここでデータベースの正規化について読む)、次にパフォーマンスの制約を満たすために非正規化することを意味します(http://) en.wikipedia.org/wiki/Denormalization [ここで非正規化についてお読みください]。

ORMを使用せずにオブジェクトをロードして保存する方法についてのあなたの質問に関して、一般的な戦略はデータアクセスオブジェクト( DAOs)を使用することです。 これは簡単な例です:

パブリックインターフェイスICustomerDao {public void insert(Customer customer)は、CustomerDaoExceptionをスローします。 public void update(ロングID、カスタマーカスタマー)はCustomerDaoExceptionをスローします。 public void delete(long id)は、CustomerDaoExceptionをスローします。 public Customer [] findAll()はCustomerDaoExceptionをスローします。 public Customer findByPrimaryKey(long id)は、CustomerDaoExceptionをスローします。 public Customer [] findByCompany(int companyId)はCustomerDaoExceptionをスローします。 }

どの言語を使用しているかは指定しませんでしたが、DAOにはhttp://www.bejug.org/confluenceBeJUG/display/BeJUG/Generic DAOの例(この例ではJavaジェネリックを使用しています)を見つけたとしても関係ありません。


0


_ 各テーブルにクラスを作成するのがよい習慣でしょうか。 もしそうなら、ormなしでデータベースにそのようなクラスをロード/保存するためのベストプラクティスは何ですか? _

あなたはORMを使っています。 オブジェクトをリレーショナルテーブルにマッピングしています。 あなたがそうするために事前に構築されたライブラリを使うかどうかはあなたの呼び出しです。 そうでなければ、おそらく既存のORMのすべての鐘と笛がなくても、自分で実装することになります。

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

ActiveRecordパターンを使用して、属性がテーブル列を定義するクラスを定義します。 このクラスの各インスタンスはデータベース内の行に対応し、新しいインスタンスを作成(および保存)することによって、データベース内に新しい行を作成します。 それについてのより多くの情報はここで利用可能です:http://en.wikipedia.org/wiki/Active_record_pattern

データマッパーパターンでは、テーブルごとにテーブルオブジェクトを定義し、テーブルの列を既存のクラスに割り当てるマッパー関数を作成します。 SQLAlchemyはデフォルトでこのパターンを使用します(ただし、SQLAlchemyの機能を別のインターフェースに適応させるActiveRecord型拡張モジュールがあります)。 このパターンの簡単な紹介はSQLAlchemyのドキュメントにあります。http://www.sqlalchemy.org/docs/05/ormtutorial.html(最初から最後まで読んだが「テーブルの作成、クラス」と題されたセクションは含まない)宣言的にMapper Allを同時に; "そのセクションではSQLAlchemyを使ったActiveRecordについて説明しています。)

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

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

SQLAlchemyのマッパー設定の詳細については、http://www.sqlalchemy.org/docs/05/mappers.htmlをご覧ください。 SQLAlchemyのようなライブラリの使用を計画していなくても、クラスをデータベーステーブルにマッピングする際に考慮しなければならない可能性があるオプションのいくつかを参照するのに役立つはずです。


0


このデータベースからクラスへの視点のアプローチは、多くのコードを非常に素早くクランキングすることにつながる可能性があります。 しかしながら、このコードのかなりの部分は何の役にも立たないか、または何らかの重大な突然変異を必要とするでしょう。 言い換えれば、表示とワークフローが一致しない特定のクラスを作成する可能性があります。

まず、アプリ、ユーザーのニーズ、一般的なワークフローを検討してください。 実際に実行可能に見えるものを思いつく あなたのディスプレイをモックします。

ディスプレイを使用するために必要なクラスに集中し、それらのニーズの後でストレージをモデル化します(db設計)。 あなたのクラスのほとんどは当然あなたのディスプレイのための解決策を提供する傾向があるので、たぶんあなたはあなたがまっすぐなテーブルクラスの少数しか持っていないということです。

がんばろう。