web-dev-qa-db-ja.com

JPA一時的な注釈とJSON

これは、JPA Transientアノテーションに関する次の質問のフォローアップです JPAには@Transientアノテーションがあるのはなぜですか?

保持したくない一時的な変数があり、一時的な注釈が付いています。ただし、レストコントローラーからJSONを生成する場合、この一時変数は出力されるJSONで使用できません。

POJO PublicationVOは派手な属性を持たず、ゲッターとセッターと1つの一時的な変数を持ついくつかのプライベート属性(永続化されている)のみを備えています。

@RequestMapping(value = { "{publicationId}"}, method = RequestMethod.GET, produces = "application/json")
@ResponseBody public PublicationVO getPublicationDetailsJSON(@PathVariable(value = "publicationId") Integer publicationId) {
    LOG.info("Entered getPublicationDetailsJSON - publicationId: " + publicationId);

    //Call method to get the publicationVO based on publicationId
    PublicationVO publicationVO = publicationServices.getPublicationByIdForRestCalls(publicationId);       
    LOG.info("publicationVO:{}", publicationVO);

    LOG.info("Exiting getPublicationDetailsJSON");
    return publicationVO;
}

PublicationVOは次のとおりです

    package com.trinity.domain.dao;

import Java.util.Calendar;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.fasterxml.jackson.annotation.JsonInclude;

@Entity
@Table(name = "publication")
public class PublicationVO {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;    
    @Column(name = "publicationName", unique = false, nullable = false, length = 200)
    private String publicationName;
    @Column(name = "publicationSource", unique = false, nullable = false, length = 45)
    private String publicationSource;

    @Column(name = "dateAdded", unique = false, nullable = false)
    private Calendar dateAdded;

    @Transient
    private float percentageProcessed;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getPublicationName() {
        return publicationName;
    }

    public void setPublicationName(String publicationName) {
        this.publicationName = publicationName;
    }

    public String getPublicationSource() {
        return publicationSource;
    }

    public void setPublicationSource(String publicationSource) {
        this.publicationSource = publicationSource;
    }

    public Calendar getDateAdded() {
        return dateAdded;
    }

    public void setDateAdded(Calendar dateAdded) {
        this.dateAdded = dateAdded;
    }

    public float getPercentageProcessed() {
        return percentageProcessed;
    }

    public void setPercentageProcessed(float percentageProcessed) {
        this.percentageProcessed = percentageProcessed;
    }

    @Override
    public String toString() {
        return "PublicationVO [id=" + id + ", publicationName=" + publicationName + ", publicationSource=" + publicationSource + ", dateAdded=" + dateAdded
                + ", percentageProcessed=" + percentageProcessed + "]";
    }
}

ログにpublicationVOのデバッグステートメントが表示される場合、一時変数は出力に含まれていますが、クライアントコードでは一時変数はjson応答に含まれていません。

どんな助けも大歓迎です。

ありがとう、ダミアン

35

私がコメントで言っていたこととは反対に、Jacksonは JacksonのHibernateモジュール のおかげでエンティティクラスのインスタンスをシリアル化するために使用される場合、JPAアノテーションを気にしているようです。

そのモジュール内には、 HibernateAnnotationIntrospector があり、ドキュメントでは

transientを使用して無視可能なフィールドを示すためのサポートを追加する単純なAnnotationIntrospector(Jacksonおよび/またはJAXB注釈とともに)。

here を見るとわかるように、Jacksonのデフォルトの動作は、検出できる@Transient注釈をチェックすることです。

したがって、最終的には、次の3つの方法のいずれかで問題を解決できます。

  1. Jacksonを設定して(HibernateAnnotationIntrospectorの setUseTransient メソッドを使用)、@Transient注釈のチェックを無効にします(実装の詳細については この回答 を参照)。
  2. PublicationVOメソッドの戻り結果としてgetPublicationDetailsJSON以外のオブジェクトを使用します。値オブジェクトのプロパティを、ある時点で返されるオブジェクトにコピーする必要があります。
  3. @Transient注釈を削除して、プロパティを永続化します(ただし、おそらく最初にこのプロパティをJPAトランジェントにした十分な理由があるので、それがオプションでない場合は理解できます)。

乾杯

28
m4rtin

JsonSerialize および JsonDeserialize 注釈を追加しました。

@Transient
@JsonSerialize
@JsonDeserialize
private String myField;
46
Fidan Hakaj

M4rtinによって提供される答えにさらに追加するだけ

最初のアプローチ-ジャクソンを構成し(HibernateAnnotationIntrospectorのsetUseTransientメソッドを使用)、@ Transientアノテーションのチェックを無効にします。

私のプロジェクトでは、フェッチされていない遅延オブジェクトでのジャクソンのシリアル化を避けるために次のスレッドに従う必要がありました フェッチされていない遅延オブジェクトでのジャクソンのシリアル化を避ける

一時的な注釈を無視しないようにプロジェクトを構成するには、次のようにHibernate4Moduleを設定します

        Hibernate4Module hm = new Hibernate4Module();
    hm.disable(Feature.USE_TRANSIENT_ANNOTATION);

このm4rtinにご協力いただきありがとうございます

21

@Transientと@JsonPropertyの両方を使用すると、動作します!

@Transient
@JsonProperty
private String mapImageSrc;
9
Clarke

それが私のために働いた:

@Transient
@JsonProperty

gETTER内(プライベートフィールド定義内ではない)

そして

@JsonAutoDetect(fieldVisibility = Visibility.ANY) 

クラスに注釈を付ける

5
Vic

ここには他の解決策はありませんでしたので、私に解決策を投稿してみましょう:

@Transient
@JsonSerialize
private String mapImageSrc;

これは、@JsonSerialize注釈がそのユースケースに対して作成されました。

2
dave0688

同じ問題がありました。以下のソリューションが私のために働いた:

@Bean
public Module hibernate5Module() {
    Hibernate5Module hnetModule = new Hibernate5Module();
    hnetModule.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
    return hnetModule;
}

M4rtinに感謝します。

2
Alok Singh

@Transientを追加してから@JsonViewを試してください

1
Sapna

com.fasterxml.jackson.annotationで@JsonIgnoreを使用し、Date変数に@JsonFormatもあります。私のために働く

0
yue wang