1

I have the following table defined with JPA:

@Data
@Entity
public class Project {

  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private long id;

  @Column(unique = true)
  private String name;

  private Integer budget;

  private String description;

  private Boolean isArchived;

  private LocalDate archivedDate;

  @Transient
  private Integer usedBudget;

  @NotNull
  @ManyToOne
  private Customer customer;
}

I have a REST-API-method getProjects() which returns all projects from the database. usedBudged is not persisted in the database and has to be calculated. In most cases when i call getProjects() i do not need the usedBudget attribute. But in one case i would like to calculate the usedBudget of the project and send it directly with the project object, so i do not have to get all projects first and do a seperate API call for each project to get the usedBudget. So in order to achieve that i added a usedBudget property to the Project entity and marked it as transient. That way it does not get persisted in the database and whenever i want to get the usedBudget, i just calculate it and set it before returning the project object. The only problem is that even if its not set(null) its getting send via JSON. Is there a way to ignore/not send this transient value whenever its set to null?

Another solution to my problem could be a helper class which extends Project and has that one additional attribute usedBudget. So whenever i need the usedBudget i would return the helper class and whenever i do not i just return the normal project(no transient usedBudget property in this case). That way i would never send useless null values.

Which of the approaches is better and is there maybe a better one?

M.Dietz
  • 900
  • 10
  • 29
  • Have you tried `@JsonInclude(Include.NON_NULL)`? see also https://stackoverflow.com/questions/11757487/how-to-tell-jackson-to-ignore-a-field-during-serialization-if-its-value-is-null – sfiss Nov 08 '19 at 14:15
  • The helper class, as you call it, has a name: DTO ([Data Transfer Object](https://en.wikipedia.org/wiki/Data_transfer_object)). This is by far the better approach. – Benoit Nov 08 '19 at 14:19

1 Answers1

1

You should have a clear separation between the objects that are persisted (the entities), and the objects that the REST api serves: They are called DTO. For instance:

@Data
public class ProjectDTO {

    private long id;
    private String name;
    private Integer budget;
    private String description;
    private Boolean isArchived;
    private LocalDate archivedDate;
    private Customer customer;
}

But if, in specific context, you need to return a Project with used budget, you can use this DTO:

@Data
public class ProjectWithBudgetDTO extends ProjectDTO {

    private Integer usedBudget;
}

Of course it requires a bit of work to create a dto from an entity, but it's quite straightforward.

This way, the API is decoupled from the persisted data model, allowing them to evolve differently. For instance you could add a new field to your database with bothering the rest api clients. Or even remove a field, and leave in the DTO with a default value.

Benoit
  • 5,118
  • 2
  • 24
  • 43
  • To create the ProjectDTO, would i just pass the Project entity as a parameter in the constructor of the ProjectDTO and copy the values i want over to the ProjectDTO? And that way i would be able to only copy over the values i want and add additional ones if i want to. – M.Dietz Nov 08 '19 at 14:47
  • @M.Dietz Yes, this is one (the simplest) possibility. Another one is to have a separate class that does the mapping entity->dto. – Benoit Nov 08 '19 at 14:50