Java JPA 瞬态注释和 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/25713884/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 00:59:26  来源:igfitidea点击:

JPA Transient Annotation and JSON

javajsonspringrestHymanson

提问by Damien Gallagher

This is a follow up to the following question on the JPA Transient annotation Why does JPA have a @Transient annotation?

这是对 JPA Transient annotation 的以下问题的跟进 为什么 JPA 有 @Transient annotation?

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.

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

刊物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.Hymanson.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 的调试语句时,transient 变量包含在输出中,但在我的客户端代码中,transient 变量未包含在json 响应中。

Any help is greatly appreciated.

任何帮助是极大的赞赏。

Thank you, Damien

谢谢你,达米安

采纳答案by m4rtin

Contrary to what I was telling you in comments, it seems that Hymanson does care about JPA annotations when used to serialize instances of entity classes thanks to the Hymanson's Hibernate module.

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

Within that module, there is an HibernateAnnotationIntrospectorthat the documentation refers to as a

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

simple AnnotationIntrospector that adds support for using Transient to denote ignorable fields (alongside with Hymanson and/or JAXB annotations).

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

And as you can see here, the default behavior of Hymanson is to check for any @Transientannotation it can find.

正如您在此处看到的,Hymanson 的默认行为是检查@Transient它可以找到的任何注释。

So in the end, your problem can be solved in either of those 3 ways :

所以最后,您的问题可以通过以下三种方式之一解决:

  1. Configure Hymanson (using HibernateAnnotationIntrospector's setUseTransientmethod) to disable the check for @Transientannotations (see this answerfor implementation details).
  2. Use another object than PublicationVOas the returned result of your getPublicationDetailsJSONmethod. You'll have to copy properties from your value object to the object being returned at some point.
  3. Remove the @Transientannotation 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).
  1. 配置 Hymanson(使用 HibernateAnnotationIntrospector 的setUseTransient方法)以禁用对@Transient注释的检查(有关实现详细信息,请参阅此答案)。
  2. 使用另一个对象而不是PublicationVO方法的返回结果getPublicationDetailsJSON。您必须将属性从值对象复制到某个时候返回的对象。
  3. 删除@Transient注释并保留该属性(但我会理解这是否不适合您,因为您可能有充分的理由首先将此属性设为 JPA 瞬态)。

Cheers

干杯

回答by Damien Gallagher

Just to add further to the answer provided by m4rtin

只是为了进一步补充 m4rtin 提供的答案

I went with the first approach - Configure Hymanson (using HibernateAnnotationIntrospector's setUseTransient method) to disable the check for @Transient annotations.

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

In my project I follwed had to follow the following thread to avoid Hymanson serialization on non fetched lazy objects Avoid Hymanson serialization on non fetched lazy objects

在我的项目中,我必须遵循以下线程以避免非获取的惰性对象上的 Hymanson 序列化避免非获取的惰性对象上的 Hymanson 序列化

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 的帮助

回答by Fidan Hakaj

I simply added JsonSerializeand JsonDeserializeannotations.

我只是添加了JsonSerializeJsonDeserialize注释。

@Transient
@JsonSerialize
@JsonDeserialize
private String myField;

回答by Clarke

I use both @Transient and @JsonProperty, then it works!

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

@Transient
@JsonProperty
private String mapImageSrc;

回答by yue wang

use @JsonIgnore in com.fasterxml.Hymanson.annotation there also is @JsonFormat for Date variable. works for me

在 com.fasterxml.Hymanson.annotation 中使用 @JsonIgnore 也有 @JsonFormat 用于 Date 变量。为我工作

回答by Sapna

Try @JsonView after adding @Transient

添加@Transient 后尝试@JsonView

回答by dave0688

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 @JsonSerializeannotation has been made for that use case.

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

回答by Vic

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

注释类

回答by Alok Singh

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。

回答by hizmarck

In my case only works with this:

在我的情况下只适用于这个:

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

I hope this can be useful for someone. Regards.

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