web-dev-qa-db-ja.com

JPAに@Transientアノテーションがあるのはなぜですか?

Javaにはtransientというキーワードがあります。なぜJPAは単に既存のJavaキーワードを使う代わりに@Transientを持っているのですか?

247
deamon

Javaのtransientキーワードは、フィールドが直列化されないことを示すために使用されますが、JPAの@Transientアノテーションは、フィールドがデータベース内で永続化されないことを示すために使用されます。

390
Jawher

意味が違うからです。 @Transientアノテーションは、JPAプロバイダに(非transient)属性を永続化させないように指示します。もう1つは、直列化フレームワークに属性を直列化しないように指示します。あなたは@Transientプロパティを持っていてそれでもそれをシリアル化したいと思うかもしれません。

105
Pascal Thivent

他の人が言ったように、@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クラスに文句を言いますPersonsetMale()およびsetFemale()メソッドが欠落しているため、Personが持続しません。

89
Esko

目的が異なります。

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によって直接永続化されます。

40
Austin D

フィールドを永続化したくない場合は、transient@ Transientの両方を使用できます。しかし、問題は、なぜ@ Transientなぜtransientが既に存在するのかということです。

@Transientフィールドは依然としてシリアル化されるので、これを使用します。

結果を取得するためにCPUを消費する計算を実行してエンティティを作成したとします。この結果はデー​​タベースに保存されません。しかし、JMSで使用するためにエンティティを他のJavaアプリケーションに送信したい場合は、JavaSEキーワードtransientではなく@Transientを使用する必要があります。そのため、他のVMで実行されている受信者は、再計算する時間を節約できます。

17
Sheng.W

私は「なぜ」の質問に答えようとします。テーブル内に多数の列を持つ巨大なデータベースがあり、プロジェクト/システムがデータベースからエンティティを生成するためのツールを使用している状況を想像してください。 (Hibernateがそれらを持っている、など...)今、あなたのビジネスロジックによってあなたが固執されないように特定のフィールドを必要とすると仮定してください。あなたはあなたのエンティティを特定の方法で "設定"しなければなりません。 Transientキーワードはオブジェクトに対して機能しますが、Java言語内では動作しますが、@ Transientは永続化タスクにのみ関連するタスクに答えるように設計されています。

0
Dima R.