JPA 瞬态注释和 JSON

2022-09-01 01:13:32

这是对JPA瞬态注释的以下问题的后续,为什么JPA具有@Transient注释?

我有一个暂时变量,我不想保留它,它被标记为瞬态注释。但是,当我想从我的 rest 控制器生成 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;
}

出版物VO如下

    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 + "]";
    }
}

当我在日志中看到 publishVO 的调试语句时,瞬态变量包含在输出中,但在我的客户端代码中,瞬态变量不包含在 json 响应中。

任何帮助都非常感谢。

谢谢你,达米安


答案 1

我只是添加了JsonSerializeJsonDeserialize注释。

@Transient
@JsonSerialize
@JsonDeserialize
private String myField;

答案 2

与我在评论中告诉您的相反,由于Jackson的Hibernate模块,当用于序列化实体类的实例时,Jackson似乎确实关心JPA注释。

在该模块中,有一个HibernateAnnotationIntrospector,文档将其称为

简单的 AnnotationIntrospector,它增加了对使用 Transient 表示可忽略字段的支持(以及 Jackson 和/或 JAXB 注释)。

正如你在这里看到的,Jackson的默认行为是检查它能找到的任何注释。@Transient

因此,最终,您的问题可以通过以下3种方式之一解决:

  1. 配置 Jackson(使用 HibernateAnnotationIntrospector 的 setUseTransient 方法)以禁用对注释的检查(有关实现详细信息,请参阅此答案)。@Transient
  2. 使用另一个对象,而不是作为方法的返回结果。您必须将属性从 value 对象复制到某个时刻返回的对象。PublicationVOgetPublicationDetailsJSON
  3. 删除注释并保留属性(但如果这不是您的选择,我会理解,因为您可能有充分的理由首先使此属性JPA瞬态化)。@Transient

干杯