Javaにはtransient
というキーワードがあります。なぜJPAは単に既存のJavaキーワードを使う代わりに@Transient
を持っているのですか?
Javaのtransient
キーワードは、フィールドが直列化されないことを示すために使用されますが、JPAの@Transient
アノテーションは、フィールドがデータベース内で永続化されないことを示すために使用されます。
意味が違うからです。 @Transient
アノテーションは、JPAプロバイダに(非transient
)属性を永続化させないように指示します。もう1つは、直列化フレームワークに属性を直列化しないように指示します。あなたは@Transient
プロパティを持っていてそれでもそれをシリアル化したいと思うかもしれません。
他の人が言ったように、@Transient
は永続化すべきではないフィールドをマークするために使用されます。この短い例を考えてみましょう。
public enum Gender { MALE, FEMALE, UNKNOWN }
@Entity
public Person {
private Gender g;
private long id;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public long getId() { return id; }
public void setId(long id) { this.id = id; }
public Gender getGender() { return g; }
public void setGender(Gender g) { this.g = g; }
@Transient
public boolean isMale() {
return Gender.MALE.equals(g);
}
@Transient
public boolean isFemale() {
return Gender.FEMALE.equals(g);
}
}
このクラスがJPAにフィードされると、gender
およびid
は永続化されますが、ヘルパーブールメソッドは永続化されません-@Transient
なしでは、基になるシステムはEntityクラスに文句を言いますPerson
にsetMale()
およびsetFemale()
メソッドが欠落しているため、Person
が持続しません。
目的が異なります。
transient
キーワードと@Transient
アノテーションには2つの目的があります。1つはシリアライゼーション、もう1つは永続性ですプログラマーとして、私たちはしばしばこれら二つの概念を一つに結びつけるが、これは一般的には正確ではない。 持続性 はそれを作成したプロセスよりも長生きする状態の特性を表します。 直列化 Javaでは、オブジェクトの状態をバイトストリームとしてエンコード/デコードするプロセスを指します。
transient
キーワードは、@Transient
よりも強い条件です。
フィールドがtransient
キーワードを使用する場合、オブジェクトがバイトストリームに変換されるときにそのフィールドはシリアル化されません。さらに、JPAはtransient
キーワードでマークされたフィールドを@Transient
アノテーションを持つものとして扱うので、そのフィールドもJPAによって永続化されません。
一方、@Transient
単独でアノテーションが付けられたフィールドは、オブジェクトがシリアル化されるとバイトストリームに変換されますが、JPAでは永続化されません。したがって、transient
キーワードは@Transient
アノテーションよりも強い条件です。
例
これは疑問を投げかける:なぜ誰かがアプリケーションのデータベースに永続化されていないフィールドをシリアル化したいのですか?現実には、シリアライゼーションは単なる永続化以上に使用されます。 Enterprise Javaアプリケーションでは、分散コンポーネント間でオブジェクトを交換するためのメカニズムが必要です。シリアル化はこれを処理するための共通の通信プロトコルを提供します。したがって、フィールドはコンポーネント間通信のために重要な情報を保持することがあります。しかし、その同じフィールドは永続性の観点からは何の価値もありません。
たとえば、最適化アルゴリズムがサーバー上で実行され、このアルゴリズムが完了するまでに数時間かかると仮定します。クライアントにとっては、最新のソリューションを用意することが重要です。そのため、クライアントはサーバーに加入し、アルゴリズムの実行フェーズ中に定期的に更新を受け取ることができます。これらの更新はProgressReport
オブジェクトを使って提供されます。
@Entity
public class ProgressReport implements Serializable{
private static final long serialVersionUID = 1L;
@Transient
long estimatedMinutesRemaining;
String statusMessage;
Solution currentBestSolution;
}
Solution
クラスは次のようになります。
@Entity
public class Solution implements Serializable{
private static final long serialVersionUID = 1L;
double[][] dataArray;
Properties properties;
}
サーバーは各ProgressReport
をそのデータベースに永続化します。サーバーはestimatedMinutesRemaining
を永続化しませんが、クライアントは確かにこの情報を気にします。したがって、estimatedMinutesRemaining
は@Transient
を使用して注釈が付けられています。アルゴリズムによって最後のSolution
が見つかると、ProgressReport
を使用せずにJPAによって直接永続化されます。
フィールドを永続化したくない場合は、transientと@ Transientの両方を使用できます。しかし、問題は、なぜ@ Transientなぜtransientが既に存在するのかということです。
@Transientフィールドは依然としてシリアル化されるので、これを使用します。
結果を取得するためにCPUを消費する計算を実行してエンティティを作成したとします。この結果はデータベースに保存されません。しかし、JMSで使用するためにエンティティを他のJavaアプリケーションに送信したい場合は、JavaSEキーワードtransient
ではなく@Transient
を使用する必要があります。そのため、他のVMで実行されている受信者は、再計算する時間を節約できます。
私は「なぜ」の質問に答えようとします。テーブル内に多数の列を持つ巨大なデータベースがあり、プロジェクト/システムがデータベースからエンティティを生成するためのツールを使用している状況を想像してください。 (Hibernateがそれらを持っている、など...)今、あなたのビジネスロジックによってあなたが固執されないように特定のフィールドを必要とすると仮定してください。あなたはあなたのエンティティを特定の方法で "設定"しなければなりません。 Transientキーワードはオブジェクトに対して機能しますが、Java言語内では動作しますが、@ Transientは永続化タスクにのみ関連するタスクに答えるように設計されています。