Spring Data JPA i UUID przy update

0

Witam,
stworzyłem sobie dla sprawdzenia jak działa UUID i myślałem, że przy każdym update mojej encji do DB UUID pozostanie takie samo, a tutaj zaskoczenie... Robię to tak:

@Entity
@Getter
@Setter
@NoArgsConstructor
public class Sample {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(updatable = false, unique = true)
    private UUID uuid = UUID.randomUUID();
    private Long age;

    public Sample(Long age) {
        this.age = age;
    }

}
    @PutMapping("/{id}")
    public Sample updateSample(@RequestBody Sample sample, @PathVariable Long id) {
        sampleDao.findById(id)
                .ifPresent(sample1 -> sample.setId(sample1.getId()));

        return sampleDao.save(sample);
    }

To ucinek z controllera, używam tu JpaRepository.. No i przy każdym pucie moje UUID się zmienia czego nie chcę. Co to powoduje?

0

Ustawiaj UUID'a setterem. Nie jestem pewien ale przy zaciągnięciu encji z bazy chyba nie bierze tego zapisanego w bazie tylko generuje przez private UUID uuid = UUID.randomUUID(); aczkolwiek mogę się mylić. Sprawdź.

0
MrMadMatt napisał(a):

Ustawiaj UUID'a setterem. Nie jestem pewien ale przy zaciągnięciu encji z bazy chyba nie bierze tego zapisanego w bazie tylko generuje przez private UUID uuid = UUID.randomUUID(); aczkolwiek mogę się mylić. Sprawdź.

Coś z tych rzeczy.
Generalnie encja JPA to nie jest taki-se obiekt javowski i wszystko mu wolno, ale ma swoje ograniczenia, inicjowanie pół chyba jest jednym z nich

0

Te pole jest nadpisywane przy każdej inicjalizacji obiektu, to nie ma prawa mieć stałej wartości. Ponadto @Column(updatable = false) z tego co widzę działa tylko na zapytania UPDATE generowane przez Hibernate'a.

0

Czyli pozostaje mi ustawiać to setterem, a nie w taki sposób?
Tylko wtedy umożliwiam komuś zmianę takiego UUID.

0

Przecież już teraz masz setter do tego pola.

Ale jeśli chcesz żeby każda instancja miała losowe UUID to w odpowiednim konstruktorze to zapewnij. Ewentualnie statyczną metodą tworzącą (czy jak to się tam nazywa)

0

Konstruktor też tego nie załatwi, bo przy robieniu Put'a i tak będę musiał pobrać UUID poprzedniej wersji i użyć settera na tej nowej - inaczej zostanie tam null. Przynajmniej tak mi się wydaje.

0

No ale co chcesz właściwie zrobić? Mieć w bazie losowe UUID którego nie możesz nadpisać? Imo bez sensu bo masz już id obiektu co tutaj pełni tą samą role co UUID.

A jak już musisz to zapisuj UUID tylko podczas tworzenia, zrób pole prywatne, nie dodawaj settera i miej nadzieje że nikt tego nie nadpisze.

1

Nie edytujesz obiektu tylko tworzysz nowy i przypisujesz mu ID z encji z bazy.
Twój PUT przyjmuje encję jako @RequestBody, które przy inicjalizacji dostaje UUID (bo ustawiłeś generowanie go podczas inicjalizacji -> private UUID uuid = UUID.randomUUID() ). Następnie pobierasz aktualny obiekt z bazy i przypisujesz temu nowemu (z requesta) jego ID, a potem go zapisujesz - stąd bierze się twój problem.

Nie używaj encji do takich rzeczy. Stwórz sobie np. UpdateSampleRequest (DTO) i w nim określ jakie pola są możliwe do aktualizacji i taki obiekt sobie przyjmij w @RequestBody, potem sobie przemapuj na pola encji (ręcznie lub jakimś mapperem, feel free). Możesz też rzućić okiem na "Validation Groups" jeśli chcesz spróbować innego podejścia i mieć bardziej "uniwersalne" DTO (ale tego używałem raz czy dwa.

@CountZero

A jak już musisz to zapisuj UUID tylko podczas tworzenia, zrób pole prywatne, nie dodawaj settera i miej nadzieje że nikt tego nie nadpisze.

Ma ustawione updatable=false, to go chroni przed zaktualizowaniem pola (nie dostanie exceptionem w twarz jak ktoś to spróbuje nadpisać, po prostu nie wejdzie to do bazy i tyle). Z setterami się zgadzam, możesz wyrzucić.

@MrMadMatt UUID wyciągane jest z bazy poprawnie

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