3

だから、私はたくさんのリレーションとルックアップテーブルを持つアプリケーションに取り組んでいますが、それはすべてこれに要約されます:

id INT (PK)
... (name, address, etc)
optcode VARCHAR (FK to Options)
typecode VARCHAR (FK to Types)

オプション

optcode VARCHAR (PK)
optdesc VARCHAR
... (more meta data, like date added, etc)

タイプ

code VARCHAR (PK)
desc VARCHAR
... (more meta data, like date added, etc)

私は休止状態を使用してこれらのテーブルにアクセスしています。一方で、オブジェクトリレーションには利点がありますが、他方では、コードに文字列を使用する方がうまく機能します。

オブジェクト関係対キー対両方の方が優れているのは何ですか?

キーを使用するだけ:

public class Person {
     private int id;
     ... (more attributes)
     private String optcode;
     private String typecode;
}
In the services:
Person person = new Person();
person.setOptcode("ABC");
person.setTypecode("XYZ");
session.save(person);

またはO/Rの方法:

public class Person {
     private int id;
     ... (more attributes)
     @JoinColumn
     private Options option;
     @JoinColumn
     private Types type;
}
In the services:
Person person = new Person();
person.setOption(new Options("ABC")); //Assume constructor fills in the 'optcode'
person.setType(new Types("XYZ"));     //Same, with 'code'
session.save(person);

永続性のほとんどの場合、私は「コード」しか持っていませんが、データを表示するときに「desc」を表示すると便利なことがよくあります

OptionsエンティティとTypesエンティティを管理する場所があるので、それらはとにかく存在しますが、オブジェクトで「コード」をラップする必要があるのは面倒です。

さまざまな方法の長所/短所は何だと思いますか?両方をPersonオブジェクトに入れて、より便利なものを使用できるようにした場合はどうなりますか?文字列を新しいOptions/Typeエンティティに押し込むだけのセッターを作成するのはどうですか?

一貫性を保つために最善の方法を特定しようとしています。現在、必要な新しいエンティティの数を最小限に抑えていますが、最終的にはすべてが休止状態のエンティティで表されます。

更新: Personエンティティはほぼ20の一意のエンティティリレーション(それぞれが異なるテーブルを指している)を持つことになります。web-uiにはおそらく各テーブルの値を含むドロップダウンリストがあるので、私は永続性に使用する「コード」があります。 関連:私は実際にPersonImpl(プレーンPOJO)とPersonEntity(Hibernate Entity)とDozerMappingを使用しています。

4

4 に答える 4

2

ORMの要点は、ナビゲートでき、リレーショナルデータベースにマップされるオブジェクトグラフを提供することです。人から、を使用してそのオプションの説明を取得できるはずですperson.getOption().getDescription()

また、を使用して、指定されたオプションの日付を持つ人を検索できる必要があります

select p from Person p where p.option.date = :date

これは、外部キーを文字列ではなく関連付けとしてマップする場合にのみ可能です。

new Option(code)あなたはあなたの人に既存のオプションを入れるために使うべきではありません、そうです。代わりに、セッションからオプションを取得またはロードする必要があります。

Person p = new Person();
p.setOption((Option) session.load(Option.class, "ABC"));
p.setType((Type) session.load(Type.class, "XYZ"));
session.save(p);

// and now, this code works as expected:
System.out.println(p.getOption().getDescription());
于 2011-09-16T16:41:43.983 に答える
1

実体関連は、特にオブジェクトをクエリするときに、一般的に言えば、コーディングを容易にすると思います。person.getOption()。getDescription()と言うよりも簡単なことは何ですか?ただし、このアプローチには欠点があります。

  • 特にsave-cascadeがある場合は、参照されるエンティティをDBからロードする必要があります。保存カスケードでは、おそらくご存知のように、HibernateはオブジェクトがDBに存在すると文句を言います。保存カスケードがないとどうなるかわかりません。
  • 参照されるエンティティは、個別のクエリを使用するか、メインエンティティのロード時に外部結合を使用してロードする必要があります。パフォーマンスの問題を引き起こす可能性があります

キーを単なるプロパティとして永続化すると、複雑な関係の場合に役立ちます。たとえば、 Hibernateによって実行される負荷が大きい大きなエンティティを参照する場合などです。このアプローチは、システムの「マスター」エンティティのロードを軽くするのに役立ちます。プロパティが必要な場合は、エンティティの読み込みを自分で行う必要があることを意味します。不変の「ルックアップ」タイプのエンティティの場合、DBに移動する代わりに、インスタンスのメモリ内マップを安全に保持し、キーでget()することができます。欠点は、エンティティ処理ロジックを分割することです。キャッシュするエンティティを覚えて、キャッシュを管理する必要があります。

一般的には、結局のところ、モデルであるエンティティを操作する方が常に良いと思います。Hibernateは、オブジェクトモデルを永続化して支援するのに役立つことに注意することを主張します。その場合、永続性のものをできるだけ多くHibernateに委任するのが論理的です。ただし、Hibernateが「適切な」モデルにうまく対応できない場合があります。多くの関係を持つエンティティ、常に使用される「ホット」エンティティなどです。これらの場合、Hibernateのメカニズムが役に立たない場合(たとえば、第2レベルのキャッシュ)このような「トリック」に頼って、自分で作業の一部を実行する必要があります。

于 2011-09-16T16:48:24.240 に答える
0

テーブルに同じ構造(「code」、「description」など)がたくさんある場合は、Hibernateの@MappedSuperclassを使用して、コードの行数を抑えることができると思います。しかし、そうでなければ、O/Rが進むべき道のようです。

于 2011-09-21T12:00:11.460 に答える
0

他のエンティティの検索が必要なエンティティにぶつかったら、人々は何をしているのだろうと思っていたので、この質問に出くわしました。それに関する主な問題は、テストであっても、インスタンスを作成するだけではもはやできないということです。私が好むアプローチは、ファクトリまたは外部(静的クラスではないなど)のビルダーに移動することです。

しかし、これに関して私が抱えている問題は、それが非常に基本的であり、エラーが発生しやすい定型文がたくさん含まれていることです。たとえば、Listingというコンテンツがあり、それが由来するソース(見つけた場所)を追跡する必要があるとします。ソースは非常に単純なエンティティですが、Listing内にそれへの参照があるので、ソースのルックアップと適切なものの挿入を行わずにリストを作成することはできなくなりました。

可能であれば、mappedByのような単純なアノテーションを使用してこれを処理することは理にかなっていますが、idまたはnameのいずれかを参照すると、コンテナーはルックアップとインジェクションを実行できます。

でも、これはすぐにわかると思います。

于 2012-01-04T23:38:01.850 に答える