Java JPA瞬态注释和JSON

Java JPA瞬态注释和JSON,java,json,spring,rest,jackson,Java,Json,Spring,Rest,Jackson,这是关于JPA瞬态注释的以下问题的后续问题 我有一个不想持久化的瞬态变量,它用瞬态注释标记。 但是,当我想从rest控制器生成JSON时,这个临时变量在输出的JSON中不可用 POJO PublicationVO是直截了当的,没有奇特的属性,只有一些私有属性(持久化的),带有getter和setter以及1个临时变量 @RequestMapping(value = { "{publicationId}"}, method = RequestMethod.GET, produces = "app

这是关于JPA瞬态注释的以下问题的后续问题

我有一个不想持久化的瞬态变量,它用瞬态注释标记。 但是,当我想从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 + "]";
    }
}
        Hibernate4Module hm = new Hibernate4Module();
    hm.disable(Feature.USE_TRANSIENT_ANNOTATION);
当我在日志中看到publicationVO的调试语句时,瞬态变量包含在输出中,但在客户端代码中,瞬态变量不包含在json响应中

非常感谢您的帮助

谢谢,,
Damien

与我在评论中告诉您的相反,Jackson在用于序列化实体类实例时似乎确实关心JPA注释,这要归功于

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

简单的AnnotationIntrospector,它增加了对使用瞬态转换的支持 表示可忽略字段(与Jackson和/或JAXB一起) 注释)

正如您所见,Jackson的默认行为是检查它能找到的任何
@Transient
注释

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

  • 配置Jackson(使用HibernateAnnotationIntrospector的方法)以禁用对
    @Transient
    注释的检查(有关实现细节,请参阅)
  • 使用
    PublicationVO
    以外的另一个对象作为
    getPublicationDetailsJSON
    方法的返回结果。您必须将属性从值对象复制到某个时刻返回的对象
  • 删除
    @Transient
    注释并持久化该属性(但如果这不是您的选项,我会理解,因为您可能有充分的理由首先使该属性成为JPA Transient)

  • 干杯

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

    我使用了第一种方法——配置Jackson(使用HibernateAnnotationIntrospector的setUseTransive方法)来禁用@Transient注释的检查

    @Transient
    @JsonSerialize
    @JsonDeserialize
    private String myField;
    
    在我的项目中,我必须遵循以下线程,以避免对未获取的惰性对象进行jackson序列化

    为了将我的项目配置为不忽略瞬态注释,我设置了Hibernate4模块,如下所示

        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 + "]";
        }
    }
    
            Hibernate4Module hm = new Hibernate4Module();
        hm.disable(Feature.USE_TRANSIENT_ANNOTATION);
    
    感谢您在此m4rtin上的帮助。我只是添加了一些注释

    @Transient
    @JsonSerialize
    @JsonDeserialize
    private String myField;
    

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

    @Transient
    @JsonProperty
    private String mapImageSrc;
    

    在com.fasterxml.jackson.annotation中使用@JsonIgnore 日期变量还有@JsonFormat。
    适用于我

    在添加@Transient后尝试@JsonView

    因为这里没有其他解决方案适用于我,让我发布我的解决方案,它是如何为我发挥作用的:

    @Transient
    @JsonSerialize
    private String mapImageSrc;
    

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

    它对我的作用:

    @Transient
    @JsonProperty
    
    在GETTER中(不在私有字段定义中)


    注释类

    我也有同样的问题。以下解决方案对我有效:

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

    多亏了m4rtin。

    在我的情况下,仅适用于以下情况:

    @Transient
    @JsonGetter(value = "transientProperty")
    public String getSomething() {
        return something;
    }
    
    我希望这对某人有用。

    关于。

    您能否编辑您的问题并发布PublicationVO的代码?没有被序列化的瞬态变量是否有合适的getter?@m4rtin-i刚刚包含了publicationVo类。是的,瞬态变量有一个getter方法。正如我在你的问题中看到的一些Spring MVC注释和Spring标记一样,你能确认JSON的序列化是由Jackson库完成的吗?是的,很抱歉,序列化是通过Jackson完成的。如果是这样的话,我需要一个非瞬态的磁场,我可以试着找出一个解决方法,但我希望有一个更干净的方法,这是一个公平的观点。我将尝试手动添加数据库列,删除临时注释,然后查看它是否有任何区别,然后返回给您。我会在早上尝试第1步,如果这不起作用,我想第2步可能是下一个逻辑步骤。非常感谢您提供的信息。第4步,它对我们很有效。杰克逊甚至无法选择关心hibernate的注释。这些人高还是什么?很高兴你找到了关于第一种方法的实施细节,我将编辑我的答案,为你的答案添加一个参考,这肯定会对寻求解决方案1的人有所帮助。最后是一些有用的东西!我用这个设置所需的各种文件创建了一个。JsonSerialize和JsonProperty似乎都能工作。我想知道是否有细微的差别,如果一个优于另一个。你甚至可以使用@JsonProperty(access=access.WRITE_ONLY)或@JsonProperty(access=access.READ_ONLY)来优化访问。这是我在使用@Transient for the my field时唯一有效的方法。谢谢,它成功了。这有助于分别定义数据库中应该保留的内容和JSON中应该保留的内容。我不知道它是否有效,但似乎我们最终在实体中混合了跨层信息。Transient用于db层(最底层),而JsonSerialize应位于UI/客户端层。我必须确保为
    @Json*
    注释导入了正确的包
    org.springframework.cloud.cloudfoundry.com.fasterxml.jackson.databind.annotation
    不起作用,但是
    com.fasterxml.jackson.databind.annotation.
    起作用了。使用注释来获得琐碎的答案和建议。我可以问一下为什么否决票?这对我有效,必须在类级别添加
    @jsonautodect
    ,谢谢!