简体   繁体   English

JPA瞬态注释和JSON

[英]JPA Transient Annotation and JSON

This is a follow up to the following question on the JPA Transient annotation Why does JPA have a @Transient annotation? 这是关于JPA瞬态注释的以下问题的后续操作为什么JPA有@Transient注释?

I have a transient variable that I do not want to persist and it is marked with the transient annotation. 我有一个我不想持久的瞬态变量,它标有瞬态注释。 However, when I want to produce JSON from my rest controller, this transient variable is not available in the outputted JSON. 但是,当我想从我的其余控制器生成JSON时,此瞬态变量在输出的JSON中不可用。

The POJO PublicationVO is straight forward with no fancy attributes, just some private attributes (that are persisted) with getters and setters and 1 transient variable. 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;
}

The PublicationVO is as follows 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 + "]";
    }
}

When I see the debug statement for publicationVO in my logs, the transient variable is included in the output but in my client code, the transient variable is not included in the json response. 当我在日志中看到publicationVO的调试语句时,瞬态变量包含在输出中,但在我的客户端代码中,瞬态变量不包含在json响应中。

Any help is greatly appreciated. 任何帮助是极大的赞赏。

Thank you, Damien 谢谢你,达米恩

I simply added JsonSerialize and JsonDeserialize annotations. 我只是添加了JsonSerializeJsonDeserialize注释。

@Transient
@JsonSerialize
@JsonDeserialize
private String myField;

Contrary to what I was telling you in comments, it seems that Jackson does care about JPA annotations when used to serialize instances of entity classes thanks to the Jackson's Hibernate module . 与我在评论中告诉你的情况相反,由于杰克逊的Hibernate模块杰克逊在用于序列化实体类的实例时似乎关心JPA注释。

Within that module, there is an HibernateAnnotationIntrospector that the documentation refers to as a 在该模块中,有一个HibernateAnnotationIntrospector ,文档引用为

simple AnnotationIntrospector that adds support for using Transient to denote ignorable fields (alongside with Jackson and/or JAXB annotations). 简单的AnnotationIntrospector,它增加了对使用Transient表示可忽略字段(以及Jackson和/或JAXB注释)的支持。

And as you can see here , the default behavior of Jackson is to check for any @Transient annotation it can find. 正如您在此处所看到的,Jackson的默认行为是检查它可以找到的任何@Transient注释。

So in the end, your problem can be solved in either of those 3 ways : 所以最后,您可以通过以下三种方式解决您的问题:

  1. Configure Jackson (using HibernateAnnotationIntrospector's setUseTransient method) to disable the check for @Transient annotations (see this answer for implementation details). 配置Jackson(使用HibernateAnnotationIntrospector的setUseTransient方法)禁用对@Transient注释的检查(有关实现详细信息,请参阅此答案 )。
  2. Use another object than PublicationVO as the returned result of your getPublicationDetailsJSON method. 使用除PublicationVO之外的其他对象作为getPublicationDetailsJSON方法的返回结果。 You'll have to copy properties from your value object to the object being returned at some point. 您必须将值对象中的属性复制到某个时刻返回的对象。
  3. Remove the @Transient annotation and persist the property (but I would understand if that is not an option for you since you probably have good reason to have made this property JPA-transient in the first place). 删除@Transient注释并保留属性(但我会理解,如果这不是你的选项,因为你可能有充分的理由首先使这个属性成为JPA瞬态)。

Cheers 干杯

Just to add further to the answer provided by m4rtin 只是为了进一步补充m4rtin提供的答案

I went with the first approach - Configure Jackson (using HibernateAnnotationIntrospector's setUseTransient method) to disable the check for @Transient annotations. 我选择了第一种方法 - 配置Jackson(使用HibernateAnnotationIntrospector的setUseTransient方法)来禁用对@Transient注释的检查。

In my project I follwed had to follow the following thread to avoid jackson serialization on non fetched lazy objects Avoid Jackson serialization on non fetched lazy objects 在我的项目中,我必须遵循以下线程以避免对未获取的惰性对象进行杰克逊序列化避免对未获取的惰性对象进行杰克逊序列化

To configure my project to not ignore transient annotations, I set up the Hibernate4Module as follows 要将我的项目配置为不忽略瞬态注释,我按如下方式设置Hibernate4Module

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

Thanks for your help on this m4rtin 感谢您对此m4rtin的帮助

I use both @Transient and @JsonProperty, then it works! 我同时使用@Transient和@JsonProperty,然后就可以了!

@Transient
@JsonProperty
private String mapImageSrc;

What it worked for me: 它对我有用:

@Transient
@JsonProperty

in the GETTER (not in the private field definition) 在GETTER中(不在私有字段定义中)

AND

@JsonAutoDetect(fieldVisibility = Visibility.ANY) 

annotating the class 注释课程

Since no other solution here worked for me, let me post my solution how it did the trick for me: 由于这里没有其他解决方案适合我,让我发布我的解决方案它是如何为我做的诀窍:

@Transient
@JsonSerialize
private String mapImageSrc;

This seems to be the best solution to me as the @JsonSerialize annotation has been made for that use case. 这对我来说似乎是最好的解决方案,因为@JsonSerialize注释已经针对该用例。

I had the same problem. 我有同样的问题。 Below solution worked for me: 以下解决方案适合我:

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

Thanks to m4rtin. 感谢m4rtin。

添加@Transient后尝试@JsonView

use @JsonIgnore in com.fasterxml.jackson.annotation there also is @JsonFormat for Date variable. 在com.fasterxml.jackson.annotation中使用@JsonIgnore,还有@JsonFormat for Date变量。 works for me 适合我

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM