10

一部のプロパティに の注釈が付けられている JPA エンティティがあります@Transient

これらのプロパティをequals/hashCode/toStringメソッドで使用する必要がありますか?

私の最初の考えはNOですが、理由はわかりません。

  • チップ?
  • アイデア?
  • 説明?
4

3 に答える 3

7

の場合toString()は異なります。好きなことを行うことができるので、 (および)toString()についてのみ説明します。equals()hashCode()

まず、ルール:オブジェクトをListMapまたはに格納する場合は、ドキュメントで指定されている標準契約に従うように およびを実装Set する必要がequalshashCodeあります。

さて、どのように実装するequals()hashCode()ですか?「自然な」アイデアはId、の一部としてマップされたプロパティを使用することequals()です。

public class User {
    ...
    public boolean equals(Object other) {
        if (this==other) return true;
        if (id==null) return false;
        if ( !(other instanceof User) ) return false;
        final User that = (User) other;
        return this.id.equals( that.getId() );
    }
    public int hashCode() {
        return id==null ? System.identityHashCode(this) : id.hashCode();
  }
}

残念ながら、このソリューションには大きな問題があります。生成された識別子を使用する場合、エンティティが永続化されるまで値が割り当てられないため、一時Setエンティティが保存される前に に追加されると、そのハッシュ コードが にある間に変更され、Setこれにより が壊れます。の契約Set

したがって、推奨されるアプローチは、ビジネス キーの一部である属性を使用することです。つまり、同じデータベース ID を持つ各インスタンスに固有の属性の組み合わせです。たとえば、User クラスの場合、これはユーザー名になります。

public class User {
    ...
    public boolean equals(Object other) {
        if (this==other) return true;
        if ( !(other instanceof User) ) return false;
        final User that = (User) other;
        return this.username.equals( that.getUsername() );
    }
    public int hashCode() {
        return username.hashCode();
  }
}

Hibernate Reference Documentation は、これを次のように要約しています。

"データベース ID を使用して等価性を実装しないでください。一意の、通常は不変の属性の組み合わせであるビジネス キーを使用してください。データベース ID は、一時オブジェクトが永続化されると変更されます。一時インスタンス (通常は切り離されたインスタンスと一緒に) がビジネス キーの属性はSet、データベースの主キーほど安定している必要はありません。オブジェクトが同じセット内にある限り、安定性を保証する必要があるだけです。- 12.1.3。オブジェクト ID の考慮hashcodeSet

"ビジネス キーの等価性を実装equals()してhashCode()使用することをお勧めします。ビジネス キーの等価性とは、equals()メソッドがビジネス キーを形成するプロパティのみを比較することを意味します。これは、実世界でインスタンスを識別するキーです (自然な候補キー)" - 4.3。equals() と hashCode() の実装

では、最初の質問に戻ります。

  • 可能であれば、ビジネス キーを使用してください。@Transient属性は、そのようなキーの一部ではない可能性が非常に高いです。
  • 不可能な場合は、識別子のプロパティを使用しますが、エンティティを 、ListMapに追加する前に割り当てられた値を取得してSetください。

こちらもご覧ください

于 2010-06-01T19:00:19.077 に答える
0

私が知っている@Transientとの 2 つの典型的な使用法は、シリアル化/永続化できないもの (リモート リソースハンドルなど) または他のものから再構築できる計算されたプロパティのいずれかに使用することです。transient

計算されたデータの場合、equals/hashCode冗長になるため、等式関係 ( ) で使用しても意味がありません。値は、等価で既に使用されている他の値から計算されます。ただし、それらを印刷することは理にかなっていますtoString(たとえば、基本価格と比率を使用して実際の価格を計算します)。

シリアライズ可能/パーシタブルでないデータの場合、依存します。シリアル化できないリソースへのハンドルを想像できますが、ハンドルが表すリソース名を比較することはできます。についても同様でtoString、おそらくハンドル リソース名を出力すると便利です。

これは私の 2 セントでした@Transient.

于 2010-06-01T17:52:57.763 に答える
0

例外は、それを放置するtransientと同時に、提供 writeObject()readObject()、処理する場所から生じる場合があります。

于 2012-05-09T07:57:31.520 に答える