Poprawne przekazywanie danych z frontu do API.

0

Załóżmy że mam 2 klasy w API (widok uproszczony)

public class Order {

    private Long idOrder;
    private Customer customer;
    private Float finalPrice;
    private Date orderDate;
}

public class Customer {

    private Long idCustomer;
    private String name;
    private String surname;
    private List<Order> orders;
}

W bazie danych analogicznie mam 2 tabele (relacja wiele do jednego):

ORDER
id_order
id_customer
final_price
order_date
CUSTOMER
id_customer
name
surname

JSON, który otrzymam w wyniku zapytania frontu o dane z powyższych tabel będzie wyglądał tak (pomijam temat DTO i zapętlenia):

    {
        "idOrder": 4,
        "customer": {
            "idCustomer": 2,
            "name": "ANNA",
            "surname": "STANEK"
        },
        "finalPrice": 5000.0,
        "orderDate": "2020-11-12T12:53:42.000+00:00"
    }

Załóżmy że na froncie, użytkownik ANNA o id_customer = 2 złożył nowe zamówienie.
Jak powinien wyglądać JSON, który przyjdzie z frontu do API z nowym zamówieniem zakładając, że insertuję tylko dane do tabeli ORDER, a id CUSTOMER jest mi już znane?

Czy nie jest tak że powinienem zrobić nową reprezentację klasy ORDER

public class OrderDTOX {

    private Long idOrder;
    private Long idCustomer
    private Float finalPrice;
    private Date orderDate;
}

i dla niej np. taki JSON?

    {
        "idCustomer": 2,
        "finalPrice": 4500.0,
        "orderDate": "2020-12-18T15:47:48.000+00:00"
    }

id_order pominąłem - nadawany jest poprzez sekwencję.

Prosiłbym o info jak podejść do tego tematu.

1

Po 1. Te klasy Order i Customer to encje bazodanowe? W takim razie w ogóle nie powinieneś ich używać w API
Po 2. Przekazujesz z frontu ID użytkownika - nie wiem dokładnie jaki masz case, ale jeżeli to ten sam użytkownik który jest zalogowany (o ile w ogóle masz jakieś security), to lepiej wyciągnać takie ID z tego security niż ufać, że w JSONie przyszły poprawne dane.
Po 3. Odpowiadając na Twoje pytanie - tak, z reguły nowy POST endpoint == nowy DTO, oczywiście są wyjątki, ale w tym przypadku robisz po prostu coś takiego

public class CreateOrderDto {
    private BigDecimal price;
    private LocalDateTime date;
}

Czy co tam jeszcze potrzebujesz w środku. Nie nazywaj tego DTOsa OrderDTO tylko niech nazwa odzwierciedla to do czego taki DTO służy.

Po 4. Nie używaj Float ani Double do reprezentowania cen, od tego masz BigDecmial jak w przykładzie wyżej
Po 5. Nie uzywaj java.util.Date, skorzystaj z LocalDate albo LocalDateTime gdy potrzebujesz datę z czasem, również jak w przykładzie wyżej.

0

@Emdzej93: dziękuję za odpowiedź i uwagi.

1

Ile jest REST API tyle jest konwencji, ale może warto przemyśl jedną z nich, a mianowicie:

Klasa OrderDto niech będzie reporezentowana w formie JSON jak najbardziej płasko jak się da, bez relacji czyli:

{
    "idOrder": 4,
    "finalPrice": 5000.0,
    "orderDate": "2020-11-12T12:53:42.000+00:00"
}

Klasa CustomerDto też niech też będzie najlżejsza jak się da:

{
    "idCustomer": 2,
    "name": "ANNA",
    "surname": "STANEK"
}

Relacje pomiędzy obiektami można reprezentować jako oddzielne endpointy:
/customers - zwraca listę klientów (CustomerDto)
/customers/2 - zwraca klienta o idCustomer równym 2
/orders - zwraca listę zamówień (OrderDto)
/orders/4 - zwraca zamówienie o idOrder równym 4
/customers/2/orders - zwraca listę zamówień dla klienta o idCustomer równym 2
/orders/4/customer - zwraca klienta dla zamówienia o idOrder równym 4

Plusem tego podejścia jest rozwiązanie zapętlania obiektów, dzięki temu Dto można ponownie używać niezależnie z której strony relacji się patrzy.
Do tworzenia obiektów oraz aktualizacji obiektów oddzielne klasy Dto.

Oczywiście jest to jedna z konwencji.

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