środa, 24 września 2014

QueryDSL metamodel generation + Spring Data

Założenie : queryDSL + Gradle + Spring Data
Oczekiwanie : wygenerowanie metaModelu do zapytań DSL
Definiowanie kwerend w czystym Stringu  jest dobre i sprawdza się często, ale takie podejście to jest podatne na błędy (error-prone).
Błędy te pojawią się nie w fazie kompilacji jak byśmy tego chcieli, ale w fazie runtime co często sprowadza się do ujawnienia błędu gdy już nasza aplikacja trafi na serwer.
Często refaktoring SQL jest bardzo trudny i samo utrzymanie takiego kodu to spore wyzwanie.(zarówno w kodzie javy wstawki SQL czy JPQL)

Ale jest na to sposób to: automatyczne generatory metadanych.
Wygląda to tak, że generator podczas fazy kompilacji generuje za nas encje jako mapowane tabele istniejące w bazie. Wtedy rozwiązuje nam się problem 'rozjazdu SQL i kodu javy'.

QueryDSL to narzędzie do obsługi zapytań SQL, które dostarcza nam generatory kodu, fluent API i współpracę z wieloma bazami również bazami NoSQL. Zapytania w QueryDSL są bardziej user-friendly i bezpieczne typologicznie.
Co jest jeszcze ważne QueryDSL integruje się Spring Data i z takiego połączenia wynikają tylko same korzyści.

Zalety :
  - dynamiczne zapytania
  - czyste i czytelne API
  - składnia weryfikowana w czasie kompilacji
  - wydaje się bardziej czytelne niż użycie Criteria API 
  - mniej  podatny na błędy niż SQL
  - synktatycznie zbliżony do SQL
  - wspiera wiele języków zapytań jak : JPA/Hibernate, MongoDB, SQL, Lucene

Wady :
  -  wymaga generacji meta-modelu 


QueryDSL vs Criteria API
- łatwiejsze tworzenie zapytań
- prostsze tworzenie dynamicznych kwerend
- less verbose

Tak na marginesie : Spring Data umożliwia tworzenie kwerend przy pomocy odpowiednio spreparowanej metody w interfejsie (method name strategy).

Ma to wiele zalet jak :
  - szybka dla prostych zapytań
  - spójna strategia nazewnictwa umożliwia łatwe rozumienie

oraz  wad :
  - totalnie nieczytelne dla bardziej skomplikowanych zapytań
  - weryfikacja poprawności w runtime
  - nie możemy tworzyć dynamicznych tworów.

Strategia Named queries oparta na mechanizmie @NamedQuery i @NamedQueries znanym z JPA czy Hibernate.
Nazwa metody pokrywa się z nazwą @NamedQuery. Oczywiście mamy możliwość parametryzacji.

Zalety tego podejścia to :
 - wsparcie dla JPQL jak i SQL
 - możemy skorzystać z istniejących już zapytań

Wady:
 - walidacja w runtime
 - nie wspiera dynamicznych rozwiązań

Strategia @Query annotation - dekorujemy metody adnotacją @Query i w niej za pomocą JPQL czy SQL definiujemy interesującą nas kwerendę.

Zalety tego podejścia to :
 - wsparcie dla JPQL jak i SQL
 - jasne i czytelne definiowane zapytania i update'y
  - walidacja w czasie inicjowania kontekstu

Wady:
 - nie wspiera dynamicznych rozwiązań

Spring Data wspiera Criteria API za pomocą JpaSpecificationExecutor<T>.
Kluczowy jest tu interfejs :
  
Jeśli stosujesz Criteria użyć statycznego modelu wygenerowanego przez jeden z opisanych w poście generatorów. Zapewnisz sobie bezpieczną typizację kwerend.
Konfiguracja jest możliwa zarówno przez XML jak i JavaConfig :
@EnableJpaRespositories

Tip : Customize your own repositories -> @NoRepositoryBean
Tip : DomainClassConverter ->  (@PathVariable("id") Book book)
Tip : HandlerMethodArgumentResolver -> Pageable i Sort bezpośrednio wbudowany w metodę kontrolera (z requestu)


Przykład zastosowania tips'ów w jakimś moim kodzie :
Zalety :
 - dynamiczne tworzenie kwerend
 - składnia weryfikowana w czasie kompilacji

Wady:
 - skomplikowane zapytania mogą być nieczytelne


 Querydsl core - główna funkcjonalność do silnika QueryDSL
 Querydsl APT - dostarcza wsparcie dla APT generatora kodu
 Querydsl JPA - wsparcie dla adnotacji JPA

QuerydslAnnotationProcessor - generuje kod dla klas oznaczonych adnotacją :  @QueryEntity czy @QueryEmbeddable

JPAAnnotationProcessor - dla klas oznaczonych @Entity czy @Embeddable

HibernateAnnotationProcessor - to samo jak dla JPAAnnotatationProcessor tylko z uzwględnieniem standardu Hibernate
 

JDOAnnotationProcessor - wsparcie dla adnotacji JDO

MongoAnnotationProcessor - dla adnotacji @Document

QueryDslPredicateExecutor - stanowi wsparcie dla predykatów QuerySQL



Konsola: -> metaModel generuje : gradle generateQueryDSL


Mój gradle.build wygląda tak:
Prosty model domenowy :

Wygenerowany meta-model:
Podpięcie z Spring Data :
Testujemy :
Kod to posta jest tutaj:)
Porównanie z podejściem jpa metaModel jest tutaj.
Widać bardzo dobrze jak bardziej przyjazdne dla programisty jest podejście QueryDSL zamiast Criteria API.
Przykład podejścia Criteria API +JPA metaModel jest w poście ->

Brak komentarzy:

Prześlij komentarz