いつ、なぜJPAエンティティはSerializableインターフェースを実装する必要がありますか?


151

質問はタイトルにあります。以下では、私の考えと調査結果のいくつかを説明しました。

私が非常に単純なドメインモデル(リレーションなしの3つのテーブル)を持っている場合、すべてのエンティティがSerializableを実装していませんでした。

しかし、ドメインモデルがより複雑になると、RuntimeExceptionが発生し、私のエンティティの1つがSerializableを実装していないと言われました。

JPA実装としてHibernateを使用しています。

私は疑問に思う:

  1. ベンダー固有の要件/動作ですか?
  2. シリアル化可能なエンティティはどうなりますか?保存または転送のためにシリアライズ可能にする必要がありますか?
  3. エンティティをシリアル化できるようにする必要があるのはいつですか。

回答:


59

これは通常、HQLクエリとネイティブSQLクエリを混在させると発生します。HQLでは、Hibernateは渡された型をDBが理解できるものにマッピングします。ネイティブSQLを実行するときは、自分でマッピングを行う必要があります。そうしない場合、デフォルトのマッピングでは、パラメーターをシリアル化してデータベースに送信します(理解できることを願って)。


これは、なぜ「たぶんどうして」という理由を説明していません
。Bozho

つまり、シリアル化可能なインターフェイスを実装せずにエンティティがDBに保存されますか?
Hanumantha_3048092

@ Hanumantha_3048092はい。エンティティマッピングSerializableは、2つの異なる概念です。
アーロンディグラ

@AaronDigulla例や疑似コードで説明してください。
sdindiver

110

JPA仕様によると:

エンティティインスタンスが分離されたオブジェクトとして(リモートインターフェイス経由などで)値によって渡される場合、エンティティクラスはSerializableインターフェイスを実装する必要があります。

「JSR 220:Enterprise JavaBeansTM、バージョン3.0 Java Persistence APIバージョン3.0、最終リリース2006年5月2日」


14
(+1)仕様を確認することは常に実り多い
Bozho

20
なぜこれが非常に多くの賛成票を持っているのかはわかりません。OPは、モデルが単純な場合は必要なかったと言っています。Javaシリアライゼーションを介してリモートでオブジェクトを送信するには、その複雑さに関係なく、常にオブジェクトをシリアライズ可能にする必要があります。明らかに、これはOPのユースケースではありません。
ロビン

休止状態についてはよくわかりませんが、他のJPAプロバイダーでは、プロバイダーがエンティティ(オブジェクト)のコピーを作成する必要がある操作があります。SerializableこれはCloneable、たとえば、永続性のコンテキストでは、より一貫性のある状況で役立ちます。
JimmyB 2015

この回答は単なる情報のダンプであり、理由を理解するのにまったく役立ちません。
クリップ

59

エンティティをネットワーク経由でSerializable転送する(シリアル化して他の表現に変換する)、httpセッションに保存する(サーブレットコンテナーによってハードディスクにシリアル化される)などの場合は、エンティティが必要です。

永続化のためだけに、Serializable少なくともHibernateでは必要ありません。しかし、それらを作ることがベストプラクティスSerializableです。


2
わからない。たぶん、私のエンティティは暗黙のうちにどこかに転送されているのでしょう。私はhibernate + spring + jsfとTomcatを使用しています。この連鎖のどこで転送が行われますか?
ローマ

たとえば@Romanは、現在のユーザー(エンティティの場合があります)とそれに関連するすべてのエンティティがセッションで終了する可能性があります。Bozhoによると、サーブレットコンテナによってディスクにシリアル化できます。
OrangeDog

これが「なぜ、いつ」という最良の答えです。晴れ!ありがとう
クリップ

13

hibernate docsによると、@ JoinColumnアノテーションを使用している間:

という名前のパラメータがもう1つありますreferencedColumnName。このパラメーターは、結合に使用されるターゲットエンティティの列を宣言します。referencedColumnName非主キー列を使用する場合、関連付けられたクラスはでなければならないことに注意してくださいSerializable


8

JSR-317仕様に言及したConorのすばらしい回答を補足するため。通常、EARプロジェクトはEJBモジュールで構成され、EJBはリモートインターフェースを介して公開されます。この1つのケースでは、エンティティBeanがリモートEJBに集約され、ネットワークを介して配線されるように構築されているため、エンティティBeanをシリアル化可能にする必要があります。

CDIなしのJEE6戦争プロジェクト:シリアライズ不可能なJPAエンティティーに裏打ちされたEJB liteを含めることができます。

CDI を使用したJEE6 warプロジェクト:セッション、アプリケーション、または会話スコープを使用するBeanはシリアライズ可能である必要がありますが、要求スコープを使用するBeanはシリアライズ可能である必要はありません。したがって、基盤となるJPAエンティティBeanは(もしあれば)同じセマンティクスに従います。


7

永続化について話すだけの場合はSerializable必要ありませんが、エンティティを作成することをお勧めしSerializableます。

私たちは、露光されている場合はdomain/ entities直接プレゼンテーション層に公開されたオブジェクト、代わりに使用してのDTO、その場合は実装する必要がありますSerializableこれらのドメインオブジェクトはHTTPSession、キャッシュ/最適化の目的でに保存できます。httpセッションは、シリアル化またはクラスタ化できます。また、JVMインスタンス間のデータ転送にも必要です。

DTO永続化レイヤーとサービスレイヤーを分離するために使用する場合、ドメインオブジェクトを非Serializable生産的で「encapsulation」に違反するものとしてマークします。その後、それはアンチパターンになります。

複合識別子

主キークラスはシリアル化可能である必要があります。

POJOモデル

エンティティインスタンスを分離されたオブジェクトとしてリモートで使用する場合、エンティティクラスはSerializableインターフェイスを実装する必要があります。

キャッシュ
さらに、clustered2番目のレベルを実装する場合cache、エンティティはでなければなりませんserializable。2番目のレベルのキャッシュエントリのキーとして使用される可能性があるSerializableため、これidentifierはJPA要件であるため、識別子を指定する必要があります。

エンティティをシリアル化するときはserialVersionUID、プライベートアクセス修飾子を明示的に指定してください。serializableクラスが明示的にを宣言しない場合、Java(TM)Object Serialization Specificationで説明されているようにserialVersionUID、シリアル化ランタイムはserialVersionUIDクラスのさまざまな側面に基づいてそのクラスのデフォルト値を計算します。デフォルトのserialVersionUID計算は、コンパイラーの実装によって異なる可能性があるクラスの詳細に非常に敏感であるため、InvalidClassExceptions逆シリアル化中に予期しない結果になる可能性があります。


6

あなたの問題は、注釈が付けられていない複合型(クラス)のフィールドを持つことに関連していると思います。このような場合、デフォルトの処理では、オブジェクトがシリアル化された形式でデータベースに格納されます(おそらく、意図したとおりではありません)。例:

Class CustomerData {
    int getAge();
    void setAge(int age);
}

@Entity
Class Customer {
  CustomerData getCustomerData();
  void setCustomerData(CustomerData data)
}

上記の場合、CustomerDataはシリアル化された形式でデータベースのバイト配列フ​​ィールドに保存されます。


5

JPA仕様

JPA仕様によれば、エンティティーは、あるSerializableJVMから別のJVMに渡す必要がある場合、またはEJBコンテナーでパッシベーションする必要があるステートフルセッションBeanで使用する場合にのみ実装する必要があります。

エンティティインスタンスが分離されたオブジェクトとして(たとえば、リモートインターフェイスを介して)値によって渡される場合、エンティティクラスはSerializableインターフェイスを実装する必要があります。

ハイバネート

Hibernateはエンティティ属性がSerializableであることのみを必要とし、エンティティ自体は必要としません。

ただし、JPA仕様を実装すると、Serializableエンティティに関するすべてのJPA要件がHibernateにも適用されます。

トムキャット

Tomcat documantationによると、HttpSession属性も次のようにする必要がありますSerializable

Apache Tomcatが正常にシャットダウンして再起動するとき、またはアプリケーションのリロードがトリガーされるときは常に、標準のManager実装は、現在アクティブなすべてのセッションを、pathname属性を介して配置されたディスクファイルにシリアル化しようとします。このような保存されたセッションはすべて、アプリケーションのリロードが完了すると、デシリアライズされてアクティブ化されます(その間にセッションが期限切れになっていない場合)。

セッション属性の状態を正常に復元するには、そのようなすべての属性がjava.io.Serializableインターフェースを実装する必要があります。

したがって、エンティティがに格納されている場合はHttpSession、を実装する必要がありますSerializable


4

クラスをシリアル化する場合、クラスはSerializableを実装する必要があります。これはJPAに直接関係するものではなく、JPA仕様ではエンティティーが直列化可能である必要はありません。Hibernateが本当にこれについて不平を言っている場合、それはHibernateのバグであると思いますが、エンティティーを直接または間接的に、エンティティーをシリアライズ可能にする必要がある何かをしていると思います。


3

それが言うhttp://www.adam-bien.com/roller/abien/entry/do_jpa_entities_have_toを参照してください。java.io.Serializableの実装は、JVMインスタンス間でIIOPまたはJRMP(RMI)を介してデータを転送するためだけに必要です。純粋なWebアプリケーションの場合、ドメインオブジェクトはキャッシュ/最適化の目的でHTTPSessionに保存されることがあります。httpセッションはシリアル化(パッシベーション)またはクラスタ化できます。どちらの場合も、コンテンツはすべてシリアライズ可能である必要があります。


1

postmanやajax、angular jsなどを使用したリモートヒットにより、JacksonのfastxmlでStackOverflow例外による繰り返しサイクルが発生する場合があるため、シリアライザを使用することをお勧めします。


1
  1. エンティティをシリアル化できるようにする必要があるのはいつですか。

2番目のレベルのキャッシュとしてディスクストアを使用してehcacheを実装する(つまり@Cacheable、エンティティまたはリポジトリ/サービスメソッドでアノテーションを使用する)にはSerializableが必要です。そうしないとNotSerializableException、エンティティがディスクキャッシュにエンティティを書き込むことができません()。


0

これは、誤って入力されたIDを2番目のパラメータとしてem.find()などに渡すときにスローされるエラーでもあります(つまり、IDではなくエンティティ自体を渡します)。JPAエンティティーをシリアライズ可能と実際に宣言する必要があることはまだわかりません。amanの説明に従ってreferenceColumnNameを使用している場合を除いて、これは実際には必要ありません。


0

JPAエンティティーがリモートEJB操作によってパラメーターまたは戻り値として使用される場合

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