Walidacja unikalnych własności obiektu.

0

Witam. Zastanawiam się jaki jest najlepszy sposób walidacji pól obiektu, które powinny być unikalne. Załóżmy, że mamy najprostszą klasę:

class Product() {
     String name;
     String description;
     BigDecimal price;
}

Nasza tabela w bazie danych odwzorowująca obiekt ma oznaczone pole name jako UNIQUE. W jaki sposób najlepiej zwalidować poprawność danych przed dodaniem kolejnego produktu? Pierwszy sposób jaki mi przychodzi do głowy, to, że mamy jakąś klasę walidującą i wygląda to tak:

  1. Sprawdzamy poprawność pól name, description czy nie są puste, czy price nie jest ujemne itp.
  2. Wykonujemy proste zapytanie sqlowe select * from products where name = "xxxx"; jeśli ono zwróci nam jakiś wynik to wyświetlamy informacje, że produkt w bazie już istnieje, jeśli nie to punkt kolejny
  3. Zapisujemy w bazie danych obiekt produkt.

Wydaje mi się jednak, że nie jest to najlepszy sposób bo pomiędzy punktem 2 i 3 ktoś, może nas uprzedzić i wtedy przy wykonaniu podpunktu 3 poleci wyjątek przy próbie zapisu, np. w springu: DuplicateKeyException

Drugi sposób jaki mi przychodzi do głowy to scenariusz, w którym usuwamy sprawdzanie z punktu 2 a w punkcie 3 łapiemy wyjątek:

public Optional<String> save(Product product)
	try {
             entityManager.persist(product);
             return Optional.empty();
       } catch(DuplicateKeyException e) {
              return Optional.of("Duplicated key");
      }
}

albo w metodzie zamiast Optionala jakis Either z vavra.

Jakie jest najlepsze podejście w takim przypadku? Drugie pytanie skoro łapiemy np. DuplicateKeyException to czy należy łapać inne wyjątki jakie mogą wyniknąć przy persist czy innych metodach CRUDowych w JPA? Są to wyjątki unchecked, więc chyba nie powinno się ich łapać, ale z 2 strony jeśli po stronie serwera wyniknie taki błąd przy persist to wtedy użytkownik nie dostanie komunikatu o błędzie, tylko poleci jakiś wpis do logów

1

1 opcja, z takich powodów jak fakt że
1)Może być więcej takich pól (np. student może mieć pesel i numer indeksu). Oczywiście to zapytanie powinno yć w obiekcie warstwu dostępu do danych
2)Nie powinno się tak robić jak zrobiłeś w 2. Przede wszystkim ten Optional jest nieczytelny, bo nie wiadomo co zwraca i raczej nie powinien zwracać takich rzeczy jak wartość błędu bazodanowego. Oczywiście w cywilizowanym kodzie warstwa DAO wyrzuca wyjątke duplikacji, jest jakiś ExceptionHandler który to przechwytuje i wszysko gra i buczy :)

poza tym jak złapiesz wyjatek w transakcji to ona się nie cofnie jeśli korzystarz z programowania aspektowego tak jak na przykład w Springu

0

@scibi92: Ok dzięki za odpowiedź. Czyli z tego co piszesz Optional to zły pomysł na zwracanie informacji o błędzie? Załóżmy, że będę teraz miał tą metodę do walidacji jak w 1 przypadku, przykładowo:

public Optional<String> validateProductData(Product product) {
       if(productDao.isProductNameExist(product.getName()) {
          return Optional.of("Product name exist");
      }
      return Optional.empty();
}

Nie jest to dobry pomysł? Jak to zrobić lepiej?

0

Ok, akurat Springa i klasę Errors znam. Bardziej chodziło mi co w przypadku co jeśli nie korzystamy np. ze Springa. Sorry za niedoprecyzowanie. Czy zwracanie informacji o powodzeniu, niepowodzeniu jako Optionala jest złą praktyką?

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