Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

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.

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.

@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

    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.

Any help is greatly appreciated.

Thank you, Damien

like image 351
Damien Gallagher Avatar asked Sep 07 '14 19:09

Damien Gallagher


People also ask

What is transient annotation in JPA?

@Transient annotation in JPA or Hibernate is used to indicate that a field is not to be persisted or ignore fields to save in the database. @Transient exist in javax. persistence package. It is used to annotate a property or field of an entity class, mapped superclass, or embeddable class.

What is @transient annotation in spring?

What is @Transient annotation in Spring? @Transient annotation is used to mark a field to be transient for the mapping framework, which means the field marked with @Transient is ignored by mapping framework and the field not mapped to any database column (in RDBMS) or Document property (in NOSQL).

What is the easiest way to ignore a JPA field during persistence?

To ignore a field, annotate it with @Transient so it will not be mapped by hibernate.

What annotation can exclude fields and properties of entity from mapping in JPA?

When persisting Java objects into database records using an Object-Relational Mapping (ORM) framework, we often want to ignore certain fields. If the framework is compliant with the Java Persistence API (JPA), we can add the @Transient annotation to these fields.


2 Answers

I simply added JsonSerialize and JsonDeserialize annotations.

@Transient @JsonSerialize @JsonDeserialize private String myField; 
like image 148
Fidan Hakaj Avatar answered Sep 28 '22 16:09

Fidan Hakaj


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.

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

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

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

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).
  2. Use another object than PublicationVO as the returned result of your getPublicationDetailsJSON method. 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).

Cheers

like image 32
m4rtin Avatar answered Sep 28 '22 17:09

m4rtin