質問はタイトルにあります。以下に、私の考えと調査結果のいくつかを説明しました。
非常に単純なドメインモデル(リレーションシップのない3つのテーブル)がある場合、すべてのエンティティはSerializableを実装しませんでした。
しかし、ドメインモデルがより複雑になると、RuntimeExceptionが発生しました。これは、エンティティの1つがSerializableを実装していないと言いました。
Jiber実装としてHibernateを使用します。
私は疑問に思う:
これは通常、HQLとネイティブSQLクエリを混在させる場合に発生します。 HQLでは、Hibernateは渡された型をDBが理解できるものにマップします。ネイティブSQLを実行するときは、マッピングを自分で行う必要があります。そうしないと、デフォルトのマッピングはパラメータをシリアル化してデータベースに送信します(理解できることを期待して)。
JPA仕様によると:
エンティティインスタンスが値によって、分離されたオブジェクトとして(たとえば、リモートインターフェイスを介して)渡される場合、エンティティクラスはSerializableインターフェイスを実装する必要があります。
「JSR 220:Enterprise JavaBeansTM、バージョン3.0 Java Persistence APIバージョン3.0、最終リリース2006年5月2日」
エンティティをワイヤ経由で転送する(他の表現にシリアル化する)必要がある場合は、エンティティをSerializable
にする必要があり、httpセッションに格納します(サーブレットセッションによってハードディスクにシリアル化されます) )など.
永続性のために、少なくともHibernateではSerializable
は必要ありません。ただし、Serializable
にすることをお勧めします。
JSR-317仕様を参照したConorのいい答えを補完するため。通常、EARプロジェクトは、リモートインターフェイスを介して公開されたEJBを持つEJBモジュールで構成されます。この1つのケースでは、エンティティBeanはリモートEJBに集約され、ネットワーク経由で配線されるように構築されるため、エンティティBeanをシリアル化可能にする必要があります。
CDIを使用しないJEE6戦争プロジェクト:シリアル化できないJPAエンティティに裏打ちされたEJBライトを含めることができます。
CDIを使用したJEE6 warプロジェクト: セッション、アプリケーション、または会話スコープを使用するBeanはシリアル化可能である必要がありますが、リクエストスコープを使用するBeanはシリアル化可能である必要はありません。 したがって、基礎となるJPAエンティティBean -同じセマンティクスに従います。
hibernate docs によると、@ JoinColumnアノテーションを使用している場合:
referencedColumnName
という名前のパラメーターがもう1つあります。このパラメーターは、結合に使用されるターゲットエンティティの列を宣言します。referencedColumnName
を非主キー列に使用する場合、関連付けられたクラスはSerializable
でなければならないことに注意してください。
あなたの問題は、注釈が付けられていない複雑なタイプ(クラス)のフィールドを持つことに関連していると思います。このような場合、デフォルトの処理では、オブジェクトをシリアル化された形式でデータベースに保存します(おそらく、意図したとおりではありません)。例:
Class CustomerData {
int getAge();
void setAge(int age);
}
@Entity
Class Customer {
CustomerData getCustomerData();
void setCustomerData(CustomerData data)
}
上記の場合、CustomerDataは、シリアル化された形式でデータベースのバイト配列フィールドに保存されます。
クラスは、シリアル化する場合はSerializableを実装する必要があります。これはJPAに直接関連しておらず、JPA仕様ではエンティティがシリアル化可能である必要はありません。 Hibernateが本当にこれについて文句を言っているのなら、それはHibernateのバグだと思いますが、直接または間接的にエンティティで何かをしていると思います。
http://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_to を参照してください。Java.io.Serializableの実装は、IIOPまたはJRMP( RMI)JVMインスタンス間。純粋なWebアプリケーションの場合、ドメインオブジェクトはキャッシュ/最適化の目的でHTTPSessionに保存されることがあります。 httpセッションは、シリアル化(パッシベーション)またはクラスター化できます。どちらの場合も、すべてのコンテンツはシリアル化可能でなければなりません。
永続性についてだけ説明する場合、Serializable
は不要ですが、エンティティをSerializable
にすることをお勧めします。
domain
を使用する代わりに、プレゼンテーション層に直接公開されているentities
/DTO
オブジェクトを公開する場合、その場合は、 Serializable
。を実装します。これらのドメインオブジェクトは、キャッシュ/最適化のためにHTTPSession
に保存できます。 http-sessionはシリアル化またはクラスター化できます。また、JVM
- instances間でデータを転送するためにも必要です。
DTO
を使用して永続層とサービス層を分離する場合、ドメインオブジェクトをSerializable
としてマークすると生産性が低下し、「encapsulation
」に違反します。その後、アンチパターンになります。
主キークラスはシリアル化可能でなければなりません。
エンティティインスタンスをリモートで分離オブジェクトとして使用する場合、エンティティクラスはSerializable
インターフェイスを実装する必要があります。
キャッシュ
さらに、clustered
第2レベルcache
を実装する場合、エンティティはserializable
でなければなりません。識別子はSerializable
である必要があります。これは、identifier
が2次キャッシュエントリのキーとして使用される可能性があるためです。
また、エンティティをシリアル化するときは、プライベートアクセス修飾子を使用して明示的なserialVersionUID
を必ず指定してください。 serializable
クラスがserialVersionUID
を明示的に宣言しない場合、シリアル化ランタイムは、説明されているように、クラスのさまざまな側面に基づいてそのクラスのデフォルトserialVersionUID
値を計算するためJava(TM)Object Serialization Specificationで。デフォルトのserialVersionUID
計算は、コンパイラの実装によって異なる可能性のあるクラスの詳細に非常に敏感であるため、逆シリアル化中に予期しないInvalidClassExceptions
が発生する可能性があります。
postmanまたはajaxまたはangular jsなどを使用してリモートヒットすると、Jackson fastxmlでStackOverflow例外を使用して繰り返しサイクルが発生する可能性があります。
jPAエンティティがリモートEJB操作によってパラメーターまたは戻り値として使用される場合
これは、間違った型のIDを2番目のパラメーターとしてem.find()などに渡すときにスローされるエラーです(つまり、IDではなくエンティティ自体を渡す)。シリアル化可能なJPAエンティティを実際に宣言する必要があることはまだわかっていません。amanの説明に従ってreferencedColumnNameを使用しているのでなければ、実際には必要ありません。
- どの時点でエンティティをシリアル化できるようにする必要がありますか?
2次キャッシュとしてdiskstoreを使用してehcacheを実装します(つまり、@Cacheable
エンティティまたはリポジトリ/サービスメソッドのアノテーションにはSerializableが必要です。そうでない場合、キャッシュはエンティティをディスクキャッシュに書き込むのに失敗します(NotSerializableException
)。