JPA @Transient field but it persists

1.2k views Asked by At

I am having difficulty with a field mapped with JPA on a Spring Boot project. In short, I have a "Request" table that contains a json field called "detail". This structure is mapped in Java with the @Entity "Request", which contains a "detail" field of the "Detail" class. This class contains several fields that will be shown in various API responses and persisted, but some of them should not be persisted in the database.

To achieve this effect, I tried annotating them with @Transient, but this did not yield the desired result (isLast & isRenewable are saved on the database json column inside request table).

To resolve this, I could certainly create another class that inherits from "Detail" and contains those fields that should not be persisted in the database, and use this class only for the API return value. This approach is feasible, but it seems like a workaround and I would like to find a more elegant solution.

If anyone has any better ideas or sees errors that I may have missed, I would be very grateful.

Below is the code that I am using:

@Slf4j
@Entity
@Getter @Setter @NoArgsConstructor
public class Request implements Serializable {

    @Transient public static final GlobalDateFormatter dateFormatter = new GlobalDateFormatter();
    @Transient public String displayName;

    private static final long serialVersionUID = 2371833240449596686L;

    @Type(type = "jsonb")
    @Column(columnDefinition = "jsonb")
    @Basic(fetch = FetchType.LAZY)
    @JsonView(RequestsJSONView.Summary.class)
    private Detail detail;

}
@Getter @Setter @AllArgsConstructor
public class Detail implements Serializable {
    

    private static final long serialVersionUID = -3445021301319058960L;


    @JsonView(RequestsJSONView.Summary.class)
    private String usernameManager;

    @Transient
    @JsonView(RequestsJSONView.Summary.class)
    private Boolean isLast;

    @Transient
    @JsonView(RequestsJSONView.Summary.class)
    private Boolean isRenewable;

    public Boolean getIsLast() {
        return isLast != null && isLast;
    }
    public Boolean getIsRenewable() {
        return isRenewable != null && isRenewable;
    }

}
1

There are 1 answers

1
Mar-Z On

The annotation @Transient is only for JPA entity fields. You are correctly using it for the displayName field.

The class Detail is not a JPA entity but just a POJO (Plain Old Java Object). There is no need to add @Transient here.

This class should be serialized as JSON and persisted in the database column Request.detail as text representation. Some of the fields should be omitted however.

You have already a class for configuration of JSON view:

public class RequestsJSONView {
    public interface Summary {
    }
}

Let us add another interface just for persisted fields:

public class RequestsJSONView {
    public interface Persisted {
    }
    public interface Summary extends Persisted {
    }
}

The Detail class will look like this:

@JsonView(RequestsJSONView.Persisted.class)
private String usernameManager;

@JsonView(RequestsJSONView.Summary.class)
private Boolean isLast;

@JsonView(RequestsJSONView.Summary.class)
private Boolean isRenewable;

And the entity field will be annotated like this:

@JsonView(RequestsJSONView.Persisted.class)
private Detail detail;