REST Obiekt zwracany

0

Cześć

Jaka jest najlepsza praktyka co do typów obiektów, jakie REST endpointy powinny zwracać . Rozchodzi się tu głównie o to czy lepiej jest stosować DTO czy stricte model.

1

Zwracasz dto, czyli struktury danych.

3

Myślę, że możesz sam to spróbować sobie przeanalizować.
Wyobraź sobie model np.:

public class Department {
  private String name;
  private LocalDate creationDate;
  private List<Employee> employees;
  private Employee head;
  // getters, setters etc.
}

Wyobraź sobie teraz następujące wymagania:

  1. Wyświetl wszystkie departamenty prezentując tylko listę ich nazw.
  2. Wyświetl wszystkie departamenty wraz z datą utworzenia i kierownikiem (head) departamentu.
  3. Wyświetl wszystkich pracowników wybranego departamentu.

Co będzie lepiej zwracać. Za każdym razem cały obiekt Department, czy może jednak projekcje w postaci dedykowanych POJO/DTO?

Nie mówiąc, o zaśmiecaniu swojego modelu adnotacjami i metodami niezbędnymi do transformacji do postaci wyjściowej (np. application/json).
Wówczas, taki model potrafi wyglądać tak (tak, widziałem podobne tworki w jednym z projektów, przy którym miałem przyjemność pracować):

@NamedQueries({
  @NamedQuery(name = "Department.findByName", query = "select d from Department d where d.name = :name"),
  @NamedQuery(name = "Department.findByHeadId", query = "select d from Department d left join fetch d.head h where h.id = :headId")
})
@NamedEntityGraph(
  name = "DepartmentWithEmployeesByName",
  attributeNodes = {
    @NamedAttributeNode(value = "name"),
    @NamedAttributeNode(value = "employees", subgraph = "employeesGraph")
  },
  subgraphs= {
    @NamedSubgraph(
      name = "employeesGraph",
      attributeNodes = {
        @NamedAttributeNode(value = "firstName"),
        @NamedAttributeNode(value = "lastName"),
        @NamedAttributeNode(value = "position")
      }
    )
  }
)
@Entity
@Table(name = "department")
@JsonPropertyOrder({"name","head","creationDate","employees"})
@JsonRootName("department")
public class Department {
  @Column(length = 100, name = "name")
  private String name;
  @Column(name = "creation_date")
  @Temporal(TemporalType.DATE)
  @Convert(converter = LocalDateJpaConverter.class)
  @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
  private LocalDate creationDate;
  @OneToMany(mappedBy = "department")
  private List<Employee> employees;
  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(name = "headId")
  private Employee head;
  
  // some endpoints require creation date in number format
  @JsonProperty("creationDateNumber")
  public Long getCreationDateNumber() {
    return creationDate.toEpochDay();
  }

  @JsonSetter("creationDateNumber")
  public void setCreationDateNumber(Long epochDay) {
    creationDate = LocalDate.ofEpochDay(epochDay);
  }
  // getters, setters etc.
}
1

DTO - w razie zmian na bazie danych i aktualizacji modelu bazy zmiany mogą rozpropagować się od razu aż do API. Na pewno tego chcesz?

1 użytkowników online, w tym zalogowanych: 0, gości: 1