JPA瞬态注释和JSON

时间:2014-09-07 19:21:01

标签: java json spring rest jackson

这是关于JPA Transient注释的以下问题的后续内容 Why does JPA have a @Transient annotation?

我有一个我不想持久的瞬态变量,它标有瞬态注释。 但是,当我想从我的其余控制器生成JSON时,输出的JSON中不会提供此瞬态变量。

POJO PublicationVO是直截了当的,没有花哨的属性,只有一些私有属性(持久化)有getter和setter以及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响应中。

非常感谢任何帮助。

谢谢你, 达明

10 个答案:

答案 0 :(得分:40)

我只是添加了JsonSerializeJsonDeserialize注释。

@Transient
@JsonSerialize
@JsonDeserialize
private String myField;

答案 1 :(得分:26)

与我在评论中告诉你的情况相反,由于Jackson's Hibernate module,杰克逊在用于序列化实体类的实例时似乎关心JPA注释。

在该模块中,文档引用的HibernateAnnotationIntrospector

  

简单的AnnotationIntrospector,它增加了对使用Transient的支持   表示可忽略的字段(与杰克逊和/或JAXB一起)   注解)。

正如您可以看到here,杰克逊的默认行为是检查它可以找到的任何@Transient注释。

所以最后,你可以通过以下三种方式解决问题:

  1. 配置Jackson(使用HibernateAnnotationIntrospector的setUseTransient方法)禁用对@Transient注释的检查(有关实现详细信息,请参阅this answer)。
  2. 使用PublicationVO之外的其他对象作为getPublicationDetailsJSON方法的返回结果。您必须将值对象中的属性复制到某个时刻返回的对象。
  3. 删除@Transient注释并保留属性(但我会理解,如果这不是你的选择,因为你可能有充分的理由让这个属性首先使JPA瞬态)。
  4. 干杯

答案 2 :(得分:19)

进一步补充m4rtin提供的答案

我采用了第一种方法 - 配置Jackson(使用HibernateAnnotationIntrospector的setUseTransient方法)来禁用对@Transient注释的检查。

在我的项目中,我必须遵循以下线程,以避免对未获取的惰性对象进行jackson序列化 Avoid Jackson serialization on non fetched lazy objects

要将我的项目配置为不忽略瞬态注释,我按如下方式设置Hibernate4Module

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

感谢您对此m4rtin的帮助

答案 3 :(得分:9)

我同时使用@Transient和@JsonProperty,然后就可以了!

@Transient
@JsonProperty
private String mapImageSrc;

答案 4 :(得分:5)

它对我有用:

@Transient
@JsonProperty
GETTER中的

(不在私有字段定义中)

AND

@JsonAutoDetect(fieldVisibility = Visibility.ANY) 

注释班级

答案 5 :(得分:1)

添加@Transient后尝试@JsonView

答案 6 :(得分:1)

由于这里没有其他解决方案适合我,让我发布我的解决方案,它是如何为我做的:

@Transient
@JsonSerialize
private String mapImageSrc;

这对我来说似乎是最好的解决方案,因为@JsonSerialize注释已针对该用例。

答案 7 :(得分:1)

我有同样的问题。以下解决方案为我工作:

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

感谢m4rtin。

答案 8 :(得分:0)

在com.fasterxml.jackson.annotation中使用@JsonIgnore 还有@JsonFormat for Date变量。 适合我

答案 9 :(得分:0)

就我而言,仅适用于此:

@Transient
@JsonGetter(value = "transientProperty")
public String getSomething() {
    return something;
}

我希望这对某人有用。 问候。