Hibernateアノテーション-フィールドアクセスとプロパティアクセスのどちらが優れていますか?


回答:


33

必要なときにいつでもアクセサにビジネスロジックを追加できるので、アクセサを好みます。次に例を示します。

@Entity
public class Person {

  @Column("nickName")
  public String getNickName(){
     if(this.name != null) return generateFunnyNick(this.name);
     else return "John Doe";
  }
}

その上、別のライブラリをミックスに投入した場合(JSON変換ライブラリ、BeanMapper、Dozer、またはゲッター/セッタープロパティに基づく他のBeanマッピング/クローニングライブラリなど)、ライブラリが永続性と同期していることが保証されますマネージャー(両方ともゲッター/セッターを使用します)。


17
これは、ORMがフィールド/プロパティにアクセスする方法であり、アプリケーションコードではないことに注意してください。フィールドアクセスを使用すると、getNickName()メソッドは期待どおりに機能します。ゲッター/セッターの外部で永続的な「プロパティ」を使用する場合も同様です。プロパティアクセスと遅延読み込みの問題に遭遇する可能性があるのは、この場所です。ですから、私はこの議論に一般的に同意しません。ただし、前回チェックしたとき、Hibernateは@Idフィールドのフィールドアクセスに問題がありました。
Rob Bygrave

11
この回答は質問とは関係ありません。Best Answer s by duffymo
Janning

9
アクセサ内にビジネスロジックがあってはなりません。それは明らかな行動ではありません。
iuriisusuk 2015

なぜこの応答マークは正しいのですか?同じようにフィールドをマッピングしてセッター/ゲッターを提供できるとは限りません。
Lucke

246

両方の議論がありますが、それらのほとんどは、特定のユーザー要件「ロジックを追加する必要がある場合」または「xxxxがカプセル化を壊す」から生じます。しかし、誰も実際には理論についてコメントせず、適切に推論された議論を与えていません。

オブジェクトを永続化するときにHibernate / JPAが実際に行っていること-まあ、それはオブジェクトの状態を永続化しています。つまり、簡単に再生できる方法で保管するということです。

カプセル化とは何ですか?カプセル化とは、アプリケーション/クライアントがデータに安全にアクセスするために使用できるインターフェースでデータ(または状態)をカプセル化することを意味し、一貫性と有効性を維持します。

これをMS Wordのように考えてください。MS Wordは、ドキュメントのモデルをメモリに保持します-ドキュメントの状態。これは、ユーザーがドキュメントを変更するために使用できるインターフェイス(一連のボタン、ツール、キーボードコマンドなど)を提供します。ただし、そのドキュメントを永続化(保存)することを選択すると、キーを押したときのセットではなく、内部状態が保存されます。それを生成するために使用されるマウスクリック。

オブジェクトの内部状態を保存してもカプセル化は解除されません-そうでなければ、カプセル化の意味とそれが存在する理由がよくわかりません。まさにオブジェクトのシリアライゼーションのようなものです。

このため、ほとんどの場合、ACCESSORSではなくFIELDSを永続化することが適切です。これは、オブジェクトが格納されたとおりにデータベースからオブジェクトを正確に再作成できることを意味します。検証は必要ありません。これは、オリジナルの作成時、およびデータベースに格納される前に行われたためです(神が禁じている場合を除き、DBに無効なデータを格納しています!!!!)。同様に、値はオブジェクトが保存される前にすでに計算されているため、値を計算する必要はありません。オブジェクトは、保存される前と同じように表示されます。実際、ゲッター/セッターに追加のものを追加することで、オリジナルの正確なコピーではないものを再作成するリスクが実際に高まります。

もちろん、この機能は理由のために追加されました。アクセサーを永続化するためのいくつかの有効な使用例があるかもしれませんが、それらは通常まれです。例としては、計算された値を保持したくない場合がありますが、値のゲッターでオンデマンドで計算しない理由を尋ねるか、ゲッターで遅延初期化する必要がある場合があります。個人的には良いユースケースを考えることはできません、そしてここでの答えのどれも実際には「ソフトウェア工学」の答えを与えません。


9
ソフトウェアエンジニアリングの答えは、アクセサの使用はDRYに違反します。
sourcedelica

1
@Martin回答の最後の段落に関してフォローアップの質問があります。あなたは「計算された値の永続化を避けたいという例があるかもしれません」と書いた。プロパティベースのアクセスを許可することで、計算値の保持を回避するにはどうすればよいですか?私はあなたがそうしないと主張しているのを知っていますが、私はここで要点をつかんでいません。説明していただけますか?
オタク2014年

4
@オタク私はそれを読み返した今、私は自分自身を完全には確信していません。この回答を書いてから2年になります。より良い例は、レガシーデータベースを使用していて、データがオブジェクトモデルとは異なる方法で表示される場合だと思います。アクセサは、2つの間のマッピングを提供できます。
マーティン

23
マッピングアクセサーの良いユースケースは、永続化実装に関連付けられていないサードパーティのエンティティークラスのサブクラスにマッピング情報を追加する必要がある場合です。これらのクラスではフィールドがプライベートであるため、アクセサをオーバーライドし、それらにマッピングアノテーションを追加する必要があります。別のオプションはXMLマッピングを使用することですが、いくつかのことはそこで行うのが非常に困難です。したがって、アノテーションが必要でサードパーティのクラスをマップする場合は、それらをサブクラス化してアクセサにアノテーションを追加するのがよいでしょう。
Elnur Abdurrakhimov 2014

5
@ElnurAbdurrakhimovいい例です。ありがとう。
Martin

79

私はフィールドへのアクセスを好みます。その方法では、各プロパティにゲッター/セッターを提供する必要がないからです。

Googleを介した簡単な調査では、フィールドアクセスが主であることが示されています(例:http://java.dzone.com/tips/12-feb-jpa-20-why-accesstype)。

フィールドアクセスはSpringが推奨するイディオムだと思いますが、それをバックアップするためのリファレンスが見つかりません。

パフォーマンスを測定しようとして、「違いはない」という結論に達した、関連するSOの質問があります。


エンティティにセッターゲッターを提供しない場合、そのフィールドの用途はどうでしょう...アプリケーションではそれを使用できません。フィールドがプライベートであるためです
anshulkatta

1
あなたのフィールドのゲッターとセッターを提供していないのは悪い習慣ですか?、私はパブリックフィールドを想定していたため、ここに私のコメントは常に正しいとは限りません。
Mathijs Segers 2014年

3
@anshulkattaカプセル化がすべての目的なので、私は本当にあなたの質問に取り組むべきだと思います。理想的には、すべてのフィールドがプライベートであり、可能であればゲッターやセッターがないはずです。これが、期待できる最高のカプセル化レベルです。パスワードチェッカーを検討してください。2つのプライベートフィールドpasswordHashおよびfailedAttempts。どちらもゲッターやセッターなしでプライベートにすることができます。これらは、ハッシュしてpasswordHashをチェックし、failedAttemptsを更新して結果を返すbool checkPassword(string password)によって使用されます。他のコードでこれら2つのフィールドにアクセスする必要はありません。
マーティン

2
@anshulkatta OOPでは、ゲッターとセッターはアンチパターンであり、それらは手続き型プログラミングに由来し、クラスを持つとカプセル化の原則を破り、多くの定型コードを生成します。つまり、コードは何度も何度も繰り返されました。オブジェクトは不変である必要があり、そのプロパティの変更が必要な場合は、プロパティの値を返すだけではない何かを行うメソッドを介して行う必要があります。
Uriel Arvizu、2016年

そうではありません。この場合の「アンチパターン」は意見の問題であり、教義ではありません。そうは言っても、フィールドへのアクセスはまだ好ましいです。より良いアイデアは、完全にORMソリューションを避けることです。適切なSQLを作成する方法を学びます。
duffymo 2016年

38

プロパティアクセサを使用する必要がある状況を次に示します。8つの具象サブクラスに継承する多くの実装の良さを備えたGENERIC抽象クラスがあるとします。

public abstract class Foo<T extends Bar> {

    T oneThing;
    T anotherThing;

    // getters and setters ommited for brevity

    // Lots and lots of implementation regarding oneThing and anotherThing here
 }

では、このクラスにどのように注釈を付ければよいでしょうか?答えは、現時点ではターゲットエンティティを指定できないため、フィールドアクセスまたはプロパティアクセスのいずれでも注釈を付けることはできません。具体的な実装に注釈を付ける必要があります。ただし、永続化されたプロパティはこのスーパークラスで宣言されているため、サブクラスでプロパティアクセスを使用する必要があります。

フィールドアクセスは、抽象ジェネリックスーパークラスを持つアプリケーションではオプションではありません。


2
タッチ。私はそのことを考えていませんでした。私はHibernateがこれらのためにいくつかのクレイジーSQLをキックアウトするに違いない。
Joseph Lust

8
この問題は、プロパティに注釈を付けないと機械的に解決するのが難しいように見えますが、永続化したい多くの実装を持つ抽象ジェネリッククラスが必要な場合はありませんでした。通常、私はクラス階層を作成して、オブジェクトをポリモーフィックにし(コードを再利用するだけではなく)そして、「たくさんのたくさんの実装」はとにかくしばしばSRPに違反します。その場合、私はおそらくそれを別々のクラスに移動します。このユースケースをより明確にする具体的な例はありますか?
Merlyn Morgan-Graham

私が持っている唯一の具体的な例は私のアプリケーションであり、500文字のコメントでは説明できません;-)
HDave

3
あなたは使用することができabstract T getOneThing()、かつabstract void setOneThing(T thing)、およびフィールドへのアクセスを使用しています。
Arturo Volpe、

33

私はプロパティアクセサーを好み、使用する傾向があります。

  • 必要に応じて、ロジックを追加できます(受け入れられた回答に記載されています)。
  • foo.getId() プロキシを初期化せずに呼び出すことができます(Hibernateを使用する場合は、HHH-3718が解決されるまで重要です)。

欠点:

  • コードが読みにくくなります。たとえば、クラス全体を参照して、そこにあるかどうかを確認する必要が@Transientあります。

しかし、「プロキシ」のないJPAプロバイダーを使用している場合は、「JPAプロバイダーがあなたに課している」という問題はありません。
Neil Stockton

13

それは本当に特定のケースに依存します-両方のオプションが理由のために利用可能です。IMOは、3つのケースに要約されます。

  1. setterには、データベースからインスタンスをロードするときに実行すべきでないロジックがいくつかあります。たとえば、一部の値の検証はセッターで行われますが、dbからのデータは有効である必要があります(そうでない場合、そこには到達しません(:);この場合、フィールドアクセスが最も適切です。
  2. setterには、dbからのインスタンスのロード中であっても、常に呼び出す必要があるいくつかのロジックがあります。たとえば、初期化されるプロパティは、いくつかの計算されたフィールドの計算に使用されます(たとえば、プロパティ-金額、計算されたプロパティ-同じインスタンスのいくつかの通貨プロパティの合計); この場合、プロパティへのアクセスが必要です。
  3. 上記のいずれの場合も-両方のオプションが適用可能であり、一貫性を維持します(この状況でフィールドアクセスが選択可能な場合は、同様の状況で常に使用します)。

私はHibernateを初めて使用し、同じ質問に苦労しています。この投稿が最も明確な答えを提供すると思います。ありがとうございました。
サム・レヴィン

12

値を設定するだけではなく、セッターで何かを実行したい場合は(たとえば、暗号化や計算)、フィールドアクセスを使用し、ゲッターのアノテーション(プロパティアクセス)は使用しないことを強くお勧めします。

プロパティアクセスの問題は、オブジェクトが読み込まれるときにセッターも呼び出されることです。暗号化を導入するまで、これは何ヶ月にもわたってうまくいきました。私たちのユースケースでは、セッターのフィールドを暗号化し、ゲッターで復号化したいと考えました。プロパティアクセスの問題は、Hibernateがオブジェクトをロードしたときに、セッターを呼び出してフィールドにデータを入力し、暗号化された値を再度暗号化していたことです。この投稿では、これについても触れてい ます。JavaHibernate:呼び出し元に応じてプロパティセット関数の動作が異なります。

フィールドアクセスとプロパティアクセスの違いを思い出すまで、これは頭痛の種です。これで、すべての注釈をプロパティアクセスからフィールドアクセスに移動しましたが、現在は正常に機能しています。


はい-私は、プロパティアクセスを使用する場合、フィールド値を設定する以外に、セッターでは何も実行できないことを発見しました。
HDave

2
+1ゲッター/セッターから遠ざける。私はprojectlombok.orgを使用 して、それらを開発者から隠しています。
bhantol 2014年

11

以下の理由から、フィールドアクセスを使用することを好みます。

  1. プロパティへのアクセスには、等号/ハッシュコードを実装したときに非常に厄介なバグにつながることができ、直接フィールドを参照する(そのゲッターを通じて反対に)。これは、ゲッターがアクセスされたときにのみプロキシが初期化され、直接フィールドアクセスは単にnullを返すためです。

  2. プロパティへのアクセスは、すべての注釈を付けする必要がありますユーティリティメソッドとして(例はaddChild /のremoveChild) @Transient

  3. フィールドアクセスを使用すると、ゲッターをまったく公開しないことで@Versionフィールドを非表示にできます。ゲッターはセッターの追加にもつながる可能性があり、versionフィールドを手動で設定しないでください(非常に厄介な問題につながる可能性があります)。すべてのバージョンの増分はを通じてトリガされなければならないOPTIMISTIC_FORCE_INCREMENTまたはPESSIMISTIC_FORCE_INCREMENT明示的なロック。


1.フィールドアクセス戦略はこれをどのように防ぎますか?これは、アクセススタイルに関係なく、プロキシの一般的な落とし穴のようです。2.本当に、それはユーティリティゲッターだけなのか?(とにかく良い議論)。3.versionフィールドのアクセサを公開することは、分離されたエンティティの代わりにDTOが使用される状況でしばしば役立ちます。
Dragan Bozanovic 2015年

1.いつプロキシが初期化されるかによります。2. 100%確実です。3.それは有効なポイントです。
Vlad Mihalcea 2015年

私の無知とテキストの解釈不足の可能性を許してください(私は英語を母国語とはしません)。明確にするために、フィールドアクセスはゲッター/セッターメソッドが必要ないときです。つまり、全体的に使用されるPOJOの場合、フィールドはパブリックですか?しかし、あなたは最初のトピックで何かを言い、リンクされたブログの投稿は反対です。私が理解したのは、プロキシとフィールドアクセスを利用する場合、equalsを使用できないことです。
MaikoID 2017年

いいえ。フィールドアクセスとは、Hibernateがリフレクションを介してフィールドを使用してエンティティ属性を読み取ることを意味します。詳細については、Hibernateユーザーガイドのアクセスタイプセクションをご覧ください。
Vlad Mihalcea 2017年

7

ORMがフィールドを更新する場合でも、フィールドを更新するとカプセル化が直接解除されるため、プロパティに注釈を付ける方が良いと思います。

これがあなたを燃やす場所の素晴らしい例です:あなたはおそらく同じ場所(フィールドかプロパティのどちらか)でHibernateバリデーターと永続化のためのアノテーションを望みます。フィールドに注釈が付けられた休止状態のバリデーターを使用した検証をテストする場合、エンティティのモックを使用して単体テストをバリデーターのみに分離することはできません。痛い。


2
そのため、バリデータアノテーションをアクセサに、パーシステンスアノテーションをフィールドに配置します
フィッシュボーン

6

プロパティアクセスとフィールドアクセスは、遅延初期化に関して微妙に異なると思います。

2つの基本Beanについて、以下のマッピングを検討してください。

<hibernate-mapping package="org.nkl.model" default-access="field">
  <class name="FieldBean" table="FIELD_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

<hibernate-mapping package="org.nkl.model" default-access="property">
  <class name="PropBean" table="PROP_BEAN">
    <id name="id">
      <generator class="sequence" />
    </id>
    <property name="message" />
  </class>
</hibernate-mapping>

そして、次の単体テスト:

@Test
public void testFieldBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    FieldBean fb = new FieldBean("field");
    Long id = (Long) session.save(fb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    fb = (FieldBean) session.load(FieldBean.class, id);
    System.out.println(fb.getId());
    tx.commit();
    session.close();
}

@Test
public void testPropBean() {
    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    PropBean pb = new PropBean("prop");
    Long id = (Long) session.save(pb);
    tx.commit();
    session.close();

    session = sessionFactory.openSession();
    tx = session.beginTransaction();
    pb = (PropBean) session.load(PropBean.class, id);
    System.out.println(pb.getId());
    tx.commit();
    session.close();
}

必要な選択に微妙な違いがあります:

Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        FIELD_BEAN
        (message, id) 
    values
        (?, ?)
Hibernate: 
    select
        fieldbean0_.id as id1_0_,
        fieldbean0_.message as message1_0_ 
    from
        FIELD_BEAN fieldbean0_ 
    where
        fieldbean0_.id=?
0
Hibernate: 
    call next value for hibernate_sequence
Hibernate: 
    insert 
    into
        PROP_BEAN
        (message, id) 
    values
        (?, ?)
1

つまり、呼び出しにfb.getId()は選択が必要ですが、必要ではありpb.getId()ません。


これは面白い!:)しかし、それは実装固有の動作だと私は確信しています。I
ウラジミールデュジェフ2009

はい、これは永続クラスのみがインストルメント化されているという事実によるものだと思います。ただし、idフィールドはビジネス上の価値がなく、アクセサーを必要としない1つのフィールドであることが多いため、注意が必要です。
モーリスペリー

6

フィールドベースのアクセスを選択する最も重要な理由を要約してみましょう。さらに詳しく知りたい場合は、私のブログのこの記事を読んでください:JPAとHibernateでのアクセス戦略–フィールドとプロパティのどちらが良いですか?

フィールドベースのアクセスは、はるかに優れたオプションです。これには5つの理由があります。

理由1:コードの読みやすさの向上

フィールドベースのアクセスを使用する場合は、エンティティ属性にマッピングアノテーションを付けます。すべてのエンティティ属性の定義をクラスの最上部に配置することで、すべての属性とそのマッピングの比較的コンパクトなビューを取得できます。

理由2:アプリケーションから呼び出されないgetterまたはsetterメソッドを省略します

フィールドベースのアクセスのもう1つの利点は、HibernateやEclipseLinkなどの永続化プロバイダーがエンティティ属性のゲッターメソッドとセッターメソッドを使用しないことです。つまり、ビジネスコードで使用してはならないメソッドを提供する必要はありません。これはほとんどの場合、生成された主キー属性またはバージョン列のセッターメソッドの場合です。永続化プロバイダーはこれらの属性の値を管理するため、プログラムで設定しないでください。

理由3:getterメソッドとsetterメソッドの柔軟な実装

永続化プロバイダーはゲッターメソッドとセッターメソッドを呼び出さないため、外部の要件を満たす必要はありません。これらのメソッドは任意の方法で実装できます。これにより、ビジネス固有の検証ルールを実装したり、追加のビジネスロジックをトリガーしたり、エンティティ属性を別のデータ型に変換したりできます。

たとえば、それを使用して、オプションの関連付けまたは属性をJavaラップできますOptional

理由4:ユーティリティメソッドを次のようにマークする必要はありません @Transient

フィールドベースのアクセス戦略のもう1つの利点は、ユーティリティメソッドに注釈を付ける必要がないことです。 @Transient。このアノテーションは、メソッドまたは属性がエンティティの永続状態の一部ではないことを永続化プロバイダーに通知します。また、フィールドタイプのアクセスでは、永続的な状態はエンティティの属性によって定義されるため、JPA実装はエンティティのすべてのメソッドを無視します。

理由5:プロキシを操作するときのバグを回避する

Hibernateは、遅延フェッチされた1対の関連付けにプロキシを使用し、これらの関連付けの初期化を制御できるようにします。このアプローチは、ほとんどすべての状況で正常に機能します。ただし、プロパティベースのアクセスを使用する場合、危険な落とし穴が生じます。

プロパティベースのアクセスを使用する場合、giberメソッドを呼び出すと、Hibernateはプロキシオブジェクトの属性を初期化します。ビジネスコードでプロキシオブジェクトを使用する場合は常にそうです。しかし、equalsとhashCodeの実装の多くは、属性に直接アクセスします。初めてプロキシ属性にアクセスする場合、これらの属性はまだ初期化されていません。


3

デフォルトでは、JPAプロバイダーはエンティティフィールドの値にアクセスし、エンティティのJavaBeanプロパティアクセサー(getter)メソッドとミューテーター(setter)メソッドを使用してそれらのフィールドをデータベース列にマップします。そのため、エンティティ内のプライベートフィールドの名前とタイプは、JPAにとって重要ではありません。代わりに、JPAはJavaBeanプロパティアクセサーの名前と戻り値の型のみを調べます。これは@javax.persistence.Accessアノテーションを使用して変更できます。これにより、JPAプロバイダーが採用する必要のあるアクセス方法を明示的に指定できます。

@Entity
@Access(AccessType.FIELD)
public class SomeEntity implements Serializable
{
...
}

AccessType列挙型で使用可能なオプションは、PROPERTY(デフォルト)とFIELDです。PROPERTYでは、プロバイダーはJavaBeanプロパティメソッドを使用してフィールド値を取得および設定します。FIELDは、プロバイダーにインスタンスフィールドを使用してフィールド値を取得および設定させます。ベストプラクティスとして、やむを得ない理由がない限り、デフォルトに固執し、JavaBeanプロパティを使用する必要があります。

これらのプロパティアノテーションは、プライベートフィールドまたはパブリックアクセサーメソッドのいずれかに配置できます。AccessType.PROPERTYJavaBeanアクセサーの代わりに(デフォルト)を使用してプライベートフィールドに注釈を付ける場合、フィールド名はJavaBeanプロパティ名と一致する必要があります。ただし、JavaBeanアクセサーに注釈を付ける場合、名前は一致する必要はありません。同様に、AccessType.FIELDフィールドの代わりにJavaBeanアクセサーを使用して注釈を付ける場合、フィールド名もJavaBeanプロパティー名と一致する必要があります。この場合、フィールドに注釈を付ける場合、それらは一致する必要はありません。一貫性を保ち、のJavaBeanアクセサAccessType.PROPERTYとのフィールドに注釈を付けるのが最善です AccessType.FIELD

同じエンティティ内でJPAプロパティアノテーションとJPAフィールドアノテーションを混在させないようにすることが重要です。これを行うと、不特定の動作が発生し、エラーが発生する可能性が高くなります。



2

フィールドアクセスを支持するもう1つのポイントは、それ以外の場合はコレクションのセッターを公開することを余儀なくされることです。永続的なコレクションインスタンスをHibernateで管理されていないオブジェクトに変更すると、データの一貫性が確実に失われるため、私にとっては悪い考えです。

したがって、デフォルトのコンストラクターで空の実装に初期化された保護フィールドとしてコレクションを用意し、それらのゲッターのみを公開することを好みます。その後、のような唯一の管理業務clear()remove()removeAll()などが可能であり、変更のHibernateは気づかない作ることがないという。


セッターを保護できるため、何も公開する必要はありません。また、これらのセッターは実装されているインターフェイスの一部ではないため、パブリックであっても簡単にアクセスできません。
HDave

2

私はフィールドを好みますが、注釈をゲッターに配置するように強制する1つの状況に遭遇しました。

Hibernate JPA実装で@Embeddedは、フィールドで動作しないようです。だから、それはゲッターに行く必要があります。そして、それをゲッターに配置したら、さまざまな@Column注釈もゲッターに配置する必要があります。(ここでは、Hibernateはフィールドとゲッターを混在させたくないと思います。)そして@Column、1つのクラスでゲッターを使用するようになったら、それを全体にわたって行うことはおそらく意味があります。


2

私はフィールドアクセサーを優先します。コードはずっときれいです。すべての注釈はクラスの1つのセクションに配置でき、コードは非常に読みやすくなっています。

プロパティアクセサーに別の問題が見つかりました。クラスにgetXYZメソッドがあり、永続プロパティに関連付けられていると注釈が付けられていない場合、Hibernateはそれらのプロパティを取得しようとするSQLを生成するため、非常に混乱するエラーメッセージが表示されます。2時間の無駄。私はこのコードを書きませんでした。私は過去に常にフィールドアクセサーを使用しており、この問題に遭遇したことはありません。

このアプリで使用されるHibernateバージョン:

<!-- hibernate -->
<hibernate-core.version>3.3.2.GA</hibernate-core.version>
<hibernate-annotations.version>3.4.0.GA</hibernate-annotations.version>
<hibernate-commons-annotations.version>3.1.0.GA</hibernate-commons-annotations.version>
<hibernate-entitymanager.version>3.4.0.GA</hibernate-entitymanager.version>

2

プロパティ経由のアクセスよりもフィールド経由のアクセスを選択する必要があります。フィールドを使用すると、送受信されるデータを制限できます。viaプロパティを使用すると、ホストとしてより多くのデータを送信し、G宗派を設定することができます(工場出荷時にほとんどのプロパティが設定されています)。




1

エンティティBeanを作成し、ゲッターアノテーションを使用しました。私たちが遭遇した問題はこれです:一部のエンティティは、いつ更新できるかに関していくつかのプロパティについて複雑なルールを持っています。解決策は、実際の値が変更されたかどうか、変更された場合に変更を許可するかどうかを決定するビジネスロジックを各セッターに含めることでした。もちろん、Hibernateは常にプロパティを設定できるため、最終的に2つのグループのセッターができました。かなり醜い。

以前の投稿を読んで、エンティティ内からプロパティを参照すると、コレクションが読み込まれないという問題が発生する可能性があることもわかりました。

結論として、私は将来、フィールドに注釈を付けることに傾倒します。


0

通常、BeanはPOJOなので、とにかくアクセサがあります。

したがって、問題は「どちらが優れているか」ではなく、単に「フィールドアクセスをいつ使用するか」です。そして答えは、「フィールド用のセッター/ゲッターが必要ないとき!」です。


4
問題は、POJOでフィールドアクセスとプロパティアクセスを混在させることができないことです。1つを選択する必要があります
Martin OConnor

本当に?忘れたに違いない。とにかく、私は常にPOJOとdアクセサーを使用します。
Vladimir Dyuzhev 2009年

JPA 2.0(この質問が行われたときはありませんでした)では、@ AccessTypeアノテーションを使用してアクセスタイプを混在させることができます。
mtpettyp 2010年

0

私はこれについて考え、メソッドアクセサを選択します

どうして?

フィールドとメソッドのアクセサーは同じですが、後でロードフィールドにロジックが必要な場合は、フィールドに配置されたすべての注釈を保存して移動します

よろしく

グルバート


0

クラスをきれいにするには、フィールドに注釈を入れてから、@ Access(AccessType.PROPERTY)を使用します



0

AccessType.PROPERTY:EJB永続化実装は、JavaBeanの「setter」メソッドを介してクラスに状態をロードし、JavaBeanの「getter」メソッドを使用してクラスから状態を取得します。これがデフォルトです。

AccessType.FIELD:状態は、クラスのフィールドから直接読み込まれ、取得されます。JavaBeanの「ゲッター」と「セッター」を記述する必要はありません。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.