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

テーブルごとにクラスを作成することをお勧めしますか? もしそうなら、そのようなクラスをオームなしでデータベースにロード/保存するためのベストプラクティスは何ですか? 簡単なコード例は本当に役に立ちます

4

8 に答える 8

10

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

于 2009-04-04T18:09:07.813 に答える
3

テーブルごとに 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;
}
于 2009-04-04T18:05:46.370 に答える
2

ほとんどの場合、テーブルをエンティティにマップする傾向がありますが、これは難しいルールではありません。問題の特定のエンティティのリポジトリが、特定のエンティティを取り巻く一般的な問題に対処する方がよい場合があります。これは、結果として、エンティティとして特に存在する必要があるテーブルがなくても、他のテーブルを処理することに交差することを意味します。

私が絶対にしないこと (依存データをエンティティで常に取得する必要がある非常に特定の計画されたケースを除く) は、エンティティまたはエンティティのコレクションを別のエンティティのプロパティとして設定することです。代わりに、そのエンティティは、親エンティティのプロパティである ID を介して検出可能になるか、親エンティティに関連する関連リポジトリを介して検出可能になります。

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

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

于 2009-07-15T16:22:23.670 に答える
1

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

理由?ソフトウェアが自分の仕事を助けることを期待するのではなく、ユーザーが自分の仕事はソフトウェアを実行することだと思い込んでしまうのはあまりにも簡単です。

明らかに、それらはある時点で交差する必要があります。Fowler の本が出発点として最適であることに同意します。しかし、彼はこの観点を強化すると思います。

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

于 2009-07-15T01:19:42.590 に答える
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; }
}
于 2009-04-04T18:07:13.557 に答える
0

良い習慣は、テーブルごとにクラスを作成することで構成されますか?もしそうなら、そのようなクラスをormなしでデータベースにロード/保存するためのベストプラクティスは何ですか?

ORMを使用しています。オブジェクトをリレーショナルテーブルにマッピングしています。事前に構築されたライブラリを使用するかどうかは、あなたの要求です。そうしないと、基本的に自分で実装することになりますが、おそらく既存のORMのすべての機能はありません。

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

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

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

ActiveRecordパターンは、セットアップと操作が簡単で、データベースを明確に表すクラスを提供します。これには、読みやすさの点で利点があります。副次的な利点として、ActiveRecordクラスの宣言型の性質は、データベーススキーマの明確でわかりやすいドキュメントとして効果的に機能します。

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

SQLAlchemyのマッパー構成の詳細については、http://www.sqlalchemy.org/docs/05/mappers.htmlを確認してください。SQLAlchemyのようなライブラリを使用する予定がない場合でも、ドキュメントは、クラスをデータベーステーブルにマッピングする際に検討する可能性のあるいくつかのオプションを確認するのに役立ちます。

于 2009-07-17T14:10:27.497 に答える
0

オブジェクト リレーショナル マッピング (ORM) の使用を計画している場合、これはテーブルの設計に影響を与える可能性があります。 たとえば、Hibernateは、同じツリー内で継承マッピング戦略が混在することを好みません。

ORM を使用しないことを具体的に示したので、従来のデータベース設計の原則に従うことができます。これは通常、クラスごとに 1 つのテーブルから始めて、第 3 正規形に正規化し (データベースの正規化についてはこちらを参照)、パフォーマンスの制約を満たすために非正規化します (非正規化についてはこちらを参照)。

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

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 にJava ジェネリックを使用したこの例が役立つ場合があります。

于 2009-07-17T13:27:24.490 に答える