Daobab - rozszerzenie JPA - kwerendy jako kod Javy, wykonywalność na kolekcjach, pełny ORM

0

Witajcie,

Wczoraj miała miejsce premiera biblioteki Daobab.

Daobab jest rozszerzeniem JPA, które współpracuje z dowolną implementacją JPA - od SpringDataJPA do standalone Hibernate.

Na co pozwala?

  1. Kwerendy jako kod Javy, w pełni sprawdzalny przez IDE np:
Select.from(daoPizza)
 .where(Where.AND()
  .and(daoPizza.colPizzaId(),Operator.EQUAL,4)
  .and(daoPizza.colName(),Operator.EQUAL,'CAPRICIOSA'))
 .result();
  1. Wykonywanie kwerend w pamięci. Np raz zaczytujesz tabelkę (np słownik), następnie wykonujesz mega szybko kwerendy na nich już bez obciążania bazy danych.

  2. Możliwość pracy na relacjach encji - Budujesz kwerendy wyciągające powiązane encje do podanego obiektu bez podania ID oraz bez podania typu obiektu.

  3. Abstrakcyjne budowanie kwerend - bez podawania konkretnych encji lub typów danych.

  4. Automatyczne obsługiwanie kwerend dotyczących kilku tabel bez sztywnego opisywania asocjacji w obiekcie Entity przy pomocy adnotacji.

Ogólnie biblioteka promuje odejście od dodawanie kolejnych metod w implementacjii DAO na rzecz umieszczania kwerend bezpośrednio w kodzie. Np:

List<Pizza> list=Select.from(daoPizza)
 .whereSelect(daoPizza.colPizzaId(),Operator.IN,
   Select.fieldList(daoPizzaPrice.colPizzaId())
     .where(daoPizzaPrice.colPrice(),Operator.GREATER_THAN,10.0))
 .result();

  for (Pizza pizza: list){
    eat(pizza);
  }

Bardzo ciekawie rozwiązana jest sprawa łączenia danych z wielu tabel (Projekcje) czy uzupełniania encji danymi z innych tabel (eager lub lazy loading).
Zachęcam do obejrzenia wielu przykładów na GitHub.

Jeśli temat jest interesujący - dużo więcej informacji znajdziecie na stronie http://www.daobab.io

Dodam że produkt jest w pełni "Made in Poland".

0
Klaudiusz Wojtkowiak napisał(a):

Witajcie,

Wczoraj miała miejsce premiera biblioteki Daobab.

Daobab jest rozszerzeniem JPA, które współpracuje z dowolną implementacją JPA - od SpringDataJPA do standalone Hibernate.

Spring nie jest implementacją JPA

  1. Kwerendy jako kod Javy, w pełni sprawdzalny przez IDE np:

Jak to się ma do Apache Deltaspike, QueryDSL i innych (JOOQ to coś nieco innego). Pobieżnie czytając to podobna idea?
Wydaje się że istnieją już takie rozwiązania. Nie warto było tam kontrybować?

Dodam że produkt jest w pełni "Made in Poland".

To zawsze cieszy

0

Te pisanie colName będzie upierdliwe (powtarzanie mappingu).
Zobaczcie jak magicznie poradzili sobie bez tego w https://code.google.com/archive/p/liquidform/ .

Jak juz doszlicie, że operacje w pamięci są często (ale po prawdzie to jest trochę it depends) szybsze niż IO do bazy (nawet uzbrojonej w dobre indeksy) to czemu nie wyrypać tej bazy całkiem ?

0

Spędziłem troszkę na czytaniu.

  1. Zauważam kolejne nowoczesne templejtowanie-wstrzykiwanie-whatever jedno-zerolinkowych DAO, repositories. W moich ustach to nie krytyka, mi sie to podoba, tylko (nieco ;) ) podważa sens tych warstw. Jestem zwolennikiem Adama Biena i to dla mnie jest OK.

  2. Implementowanie relacyjnych interfejsów http://www.daobab.io/dao_relations.html . Mi się podoba

@Entity @Table(name="PIZZA")
public class Pizza implements RelatedToPizza

Użyłem bardzo podobnego pomysłu, i dobrze daje jasność kodu. Natomiast pod względem ortodoksji teoretycznie JPA ma perzystować POJO, w odróżnieniu od EJB2. Nie pierwszy raz, historia (po heglowsku) zatacza koło, czy spiralę ... (wiem, wiem, to ma zupełnie inny sens niż EJB2)

0

Drobny bug w dokumentacji: http://www.daobab.io/dao_extend_to_daobab.html

	@Column(name="PIZZA_ID")
	public default DaoColumn<Pizza,Integer> colName(){
		return define("pizzaId");
	};
	
	@Column(name="NAME")
	public default DaoColumn<Pizza,String> colName(){
		return define("name");
	};

Nie powinno być dwa razy colName.

2
  1. Hmm, a jaki problem to rozszerzenie rozwiązuje?
  2. Benchamark podany bez żadnych jednostek, czy przypadkiem nie jest tak, że włączenie cache drugiego poziomu w hibernate, spowoduje, że wyniki będą porównywalne?
0

Głównym celem dla tej biblioteki jest umożliwienie pisania kwerend jako kodu javowego.
Wyobraźcie sobie bazę danych która ma np 100 tabel i sytuacje w której dla 50 tabel mamy zrobić metodę wyciągającą ostatnich 50 rekordów z flagą true.
Co jest lepsze - jeden generyczny abstract DAO który gromadzi większość metod, 50x duplikacja kodu w różnych DAO, model mieszany?
Każdy z tych rozwiązań jest de facto antypatternem.
Co jeśli mamy do napisania wiele takich metod dla różnych DAO?
Zwróćcie uwagę że DAO w Daobabie nie ma tak naprawdę żadnych metod.
Jeśli kwerenda staje się kodem Javy, podlega walidacji przez IDE. Możliwy jest wówczas jego łatwy refactoring. Kod staje się pewny, modyfikowalny, plastyczny.
Logika działania kwerendy jest widoczna od razu a jej ewentualna modyfikacja jest prosta. Jeśli kwerenda stanowi javowy kod prywatnej metody a nie jest sama wystawioną publiczną metodą, masz pewność że jej modyfikacja jest zawsze bezpieczna. Nie zastanawiasz się czy może zrobić jeszcze jedną, nową metodę, aby przypadkiem czegoś nie zepsuć.

Druga sprawa - cache. Niezwykle przydane jest to, że za pomocą jednego interfejsu, z twojego DAO automatycznie robi się decorator, który zamiast łączyć się z bazą, zwraca prawie natychmiast wyniki kwerendy z cache, a sam cache odświeża w tle wg odpowiedniej logiki. Aplikacja dostaje wówczas ogromnego kopa wydajnościowego, nie zmieniając swojej logiki biznesowej.

Trzecia sprawa - wynik kwerend staje się buforem na którym można wykonywać inne kwerendy. Loguje się do twojej apliakcji konkretny klient, a ty w jednym selekcie wyciągasz wszystkie jego dane i trzymasz je w jego sesji. Teraz wszystkie rekordy które on przegląda - otrzymuje od razu, ponieważ wykonujesz kwerendy SQLowe na bufforze a nie na tabeli tysięcy klientów.

Czwarta - dzięki relacjom możesz robić prawdziwe cuda. To co mi teraz przychodzi do głowy to np wstrzyknąć wszystkie DAO mające relacje np do klienta (uprawnienie, historia, szczegóły ito) i np ustawić tam flagi nieaktywne... wystarczy do tego jedna prosta metoda wywołana w pętli dla każdego z tych DAO, która przyjmie jakikolwiek obiekt, mający relację do klienta). Wszystko bez constraintów w bazie.

@jarekr000000, dlaczego nie drop database? Dlatego, że aplikacje miewają X microserwisów które pracują równolegle na Y serwerów. Mamy X*Y równoległych instancji i chcemy mieć wspólną bazę danych. Dodatkowo możemy mieć Z aplikacji pracujących na tych samych danych.

Do tej pory development aplikacji opartych na Daobabie przechodził bardzo szybko, płynnie i bez większych problemów. Różnice były widoczne od razu.
Proszę nie piszcie tak po polsku, że wszystko kto inny polak zrobi jest bez sensu i w ogóle po co to, doszukując przede wszystkim wad a nie zalet. Czy to naprawdę taki problem, że ktoś coś zrobił bo np sprawiło mu to frajdę - naprawdę musi się z tego tłumaczyć? Co z tego, że są również biblioteki, które podejmują temat upraszczania połączenia do bazy, skoro każde z nich dostarcza tylko cząstkę tych funkcjonalności, które są zawarte w Daobabie?

0

Głównym celem dla tej biblioteki jest umożliwienie pisania kwerend jako kodu javowego.

Nie bardzo rozumiem. Criteria API jest stare jak świat...

ty w jednym selekcie wyciągasz wszystkie jego dane i trzymasz je w jego sesji

Genialny plan na OOM.

zwraca prawie natychmiast wyniki kwerendy z cache
otrzymuje od razu, ponieważ wykonujesz kwerendy SQLowe na bufforze a nie na tabeli tysięcy klientów

Doskonały plan w środowiskach rozproszonych/mikroserwisowych, gwarantuje rozjazd niemalże momentalnie. Cache używa się świadomie, kiedy wiadomo że można. Jakieś cuda na kiju robione przez DAO "automatycznie" to słaby pomysł.

@jarekr000000 nie przesadzajmy, jakiś persistent data store jest ci potrzebny, czy to będzie jakaś baza, czy jakaś lista eventów czy cokolwiek innego to akurat bez większego znaczenia.

0

ty w jednym selekcie wyciągasz wszystkie jego dane i trzymasz je w jego sesji

Genialny plan na OOM.

zwraca prawie natychmiast wyniki kwerendy z cache
otrzymuje od razu, ponieważ wykonujesz kwerendy SQLowe na bufforze a nie na tabeli tysięcy klientów

Doskonały plan w środowiskach rozproszonych/mikroserwisowych, gwarantuje rozjazd niemalże momentalnie. Cache używa się świadomie, kiedy wiadomo że można. Jakieś cuda na kiju robione przez DAO "automatycznie" to słaby pomysł.

http://daobab.io/daobab_cache.html - polecam fragment "Whent to use cache" i "When not to use cache"

0
Klaudiusz Wojtkowiak napisał(a):

Głównym celem dla tej biblioteki jest umożliwienie pisania kwerend jako kodu javowego.

No ale czy ORMy tego właśnie nie zapewniają?

Wyobraźcie sobie bazę danych która ma np 100 tabel i sytuacje w której dla 50 tabel mamy zrobić metodę wyciągającą ostatnich 50 rekordów z flagą true.
Co jest lepsze - jeden generyczny abstract DAO który gromadzi większość metod, 50x duplikacja kodu w różnych DAO, model mieszany?
Co jeśli mamy do napisania wiele takich metod dla różnych DAO?

Czy tu genericsy nie sparwdziłyby się w sam raz? :-) Jedna implementacja i tylko sobie zmieniasz Encję, a nie robisz 50 implementacji.

0

Czy tu genericsy nie sparwdziłyby się w sam raz? :-) Jedna implementacja i tylko sobie zmieniasz Encję, a nie robisz 50 implementacji.

Naprawdę? Załóżmy że na każda tabele masz 5 specyficznych kwerend.
Umieszczasz 5*100 różnych metod. Wszystkie publiczne. Robisz abstracta z totalnym bałaganem. I zawsze 99% metod wali błędem. Jedna wielka klasa, wspólna dla wszystkich developerów. Merge horror.

To tak jak byś chciał kodzić w jednej jedynej klasie.

Poza tym w takich genericach musisz tak naprawdę przygotowywać kwerendę w postaci Stringa i wchodzisz na pole minowe literówek, błędnych typów itp id. Nie mówiąc już o refaktoringu bazy danych czy encji.

W Daobabie nie masz takich problemów, bo każda kwerenda może być exponowana do woli - jak każdy kod javowy.
Jeśli zechcesz kwerenda będzie prywatna lub będzie miała taki zakres dostępności jaki ustawisz.
Jeśli zechcesz możesz ja zapisać w interfejsie i wystawiać poprzez implementację
Możesz nawet pisać abstrakty a więc tworzyć kwerendy dotyczcie konkretnych pól lub typów pól w oderwaniu od konkretnych encjii i dao, następnie implementować je wyłącznie dla danych które spełniają warunki i mieć pewność, że nie popełnisz błędu. Poza tym - zawsze bez boilerplate.

Np raz taka metoda abstrakcyjna, która możesz umieścić gdziekolwiek np interfejsie:

	public <D extends IDaoRelatedToInsertDate<E>,E extends RelatedToInsertDate> Integer setDisabled(D dao,ColumnDefinition<E, BigDecimal, BigDecimal> columnToSet,Date date){
		return Update.to(dao)
				.set(columnToSet, BigDecimal.ZERO)
				.where(dao.colInsertDate(),Operator.GREATER_THAN,date)
				.executeUpdateTransactional();
	}

Zasetuje ci wartość '0' w polu który ty podasz w drugim parametrze, na tabelce do której dotyczy dao wskazane w parametrze pierwszym, pod warunkiem że tabelka ta będzie miała datę większa niż wskazana. Nie będziesz mógł podać innego DAO, które tych warunków nie spełnia. Po prostu nie będziesz miał MOŻLIWOŚCI aby popełnić błąd, a ten kod będziesz mógł bez kłopotu automatycznie refaktoryzować w przyszłości.

To dużo lepsza opcja niż Generici. W ogóle kod w interfejsach, powinien teraz wypierać klasy abstrakcyjne. Pozwala to na swobodne komponowanie logiki klas poprzez odpowiednie implementowanie konkretnych interfejsów. Klasa abstrakcyjna jest jedna, natomiast interfejsów może być wiele. Niestety w przypadku Dao to zawsze był problem, ponieważ Dao wymaga stanu aby mieć połączenie do bazy, natomiast interfejsu stanu nie maja.
Daobab pozwala na programowanie w interfejsach, komponowanie logiki i podawanie stanu poprzez wstrzykiwanie odpowiednich Dao do klas z logik biznesowa.
To zreszta otwiera DAO na korzyści programowania funkcyjnego.

1
Klaudiusz Wojtkowiak napisał(a):

Czy tu genericsy nie sparwdziłyby się w sam raz? :-) Jedna implementacja i tylko sobie zmieniasz Encję, a nie robisz 50 implementacji.

Naprawdę? Załóżmy że na każda tabele masz 5 specyficznych kwerend.
Umieszczasz 5*100 różnych metod. Wszystkie publiczne. Robisz abstracta z totalnym bałaganem. I zawsze 99% metod wali błędem. Jedna wielka klasa, wspólna dla wszystkich developerów. Merge horror.

To tak jak byś chciał kodzić w jednej jedynej klasie.

Argumentujesz mniej więcaj tak: bierzesz skrajny przykład: 1 klasa jest zła (z czym raczej wszyscy się zgodzą), baobab jest lepszy, bo nie jest zły.
Nie wiem dlaczego upierasz się na 1 klasę, przecież możesz mieć generyka dla tego topN, a dla reszty zgodnie potrzebami. Nie mów, że w daobabie nie musisz gdzieś upychać tych 5*X specyficznych zapytań? Skoro są specyficzne, to gdzieś muszą wystąpić.

@Shalom zresztą już Ci napisał w tym wątku, że idea Criteria API jest trochę znana.

Poza tym w takich genericach musisz tak naprawdę przygotowywać kwerendę w postaci Stringa i wchodzisz na pole minowe literówek, błędnych typów itp id. Nie mówiąc już o refaktoringu bazy danych czy encji.

Zależy jak to zrobisz, np. https://www.boraji.com/hibernate-5-criteria-query-example nie wydaje się używać kwerend w postaci Stringów.

Ja nadal nie widzę, gdzie ta różnica między, np. implementacją hibernate skonfigurowane z second level cacheem i użyciem criteria api do budowania kwerend, a daobabem.

W żadnym razie nie oceniam daobaba źle/dobrze, tylko staram się zrozumieć tę różnicę, gdzie robi różnicę.

0
Klaudiusz Wojtkowiak napisał(a):

@jarekr000000, dlaczego nie drop database? Dlatego, że aplikacje miewają X microserwisów które pracują równolegle na Y serwerów. Mamy X*Y równoległych instancji i chcemy mieć wspólną bazę danych. Dodatkowo możemy mieć Z aplikacji pracujących na tych samych danych.

Już ktoś to zauważył, ale to chyba najsłabsze mikroserwisy pod słończem. (Nawet w monolitach, (które tak lubię ) promuje od jakiegoś czasu, ze jak już baza to osobna na pakiet - coby nie robić powiązań).

Do tej pory development aplikacji opartych na Daobabie przechodził bardzo szybko, płynnie i bez większych problemów. Różnice były widoczne od razu.
Proszę nie piszcie tak po polsku, że wszystko kto inny polak zrobi jest bez sensu i w ogóle po co to, doszukując przede wszystkim wad a nie zalet. Czy to naprawdę taki problem, że ktoś coś zrobił bo np sprawiło mu to frajdę - naprawdę musi się z tego tłumaczyć? Co z tego, że są również biblioteki, które podejmują temat upraszczania połączenia do bazy, skoro każde z nich dostarcza tylko cząstkę tych funkcjonalności, które są zawarte w Daobabie?

Na ogół twórcom frameworkow development w nich idzie dużo lepiej ... niż potem biednym programistom, którzy tego frameworku nie wymyślili. Trudno mi krytykowac wasz, o tyle, że już samo JPA uważam za niebezpieczne w pracy zespołowej i w nowych projektach unikam - zbyt magiczne i błędogenne. Daobab sprawia wrażenie podnoszenia magiczności o jeszcze jeden poziom wyżej.
Zresztą niedaloko od waszego jest projekt QueryDSL, który w werji QueryDSL / JPA to niestety horrorek magiczności. (Gdzie QueryDSL /SQL jest już całkiem używalny - tylko troche gorszy od JOOQ).

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