27 marca 2007

Nauka Java Persistence z Apache Maven 2 i dostawcami JPA: OpenJPA, Hibernate i TopLink

Nic nie zastąpi nauki poprzez praktykę. Nie wszyscy mają czas, aby wszystko praktycznie sprawdzić, więc część rzeczy uczymy się wierząc słowu pisanemu. W przypadku mojej lektury specyfikacji Java Persistence API (JPA) było inaczej - zdecydowałem się na zestawienie środowiska, które zautomatyzowałoby mi wykonywanie testów jednostkowych pisanych z TestNG i jednocześnie uatrakcyjniałyby poznawanie JPA.

Najpierw powstał artykuł Java Persistence API z OpenJPA i Derby oraz TestNG z Eclipse IDE w tle, po którym dzisiejszego wieczoru napisałem kolejny będący kontynuacją wspominanego - Nauka Java Persistence z Apache Maven 2 i dostawcami JPA: OpenJPA, Hibernate i TopLink. W ten sposób nie tylko, że mogę uruchamiać proste programy (testy) bez konieczności każdorazowego zestawiania środowiska, ale również wykonywać je z wybranym dostawcą JPA - Apache OpenJPA, Hibernate oraz TopLink Essentials. A wszystko zaczęło się tak niewinnie...

Podczas lektury specyfikacji JPA rozdział 4.6 Wyrażenia warunkowe, natrafiłem na pewne zapisy, których nie mogłem zrozumieć, a może po prostu chciałem zaprezentować je w postaci kawałka kodu? Nieważne! Jak to bywało do tej pory, tak i zrobiłem i tym razem - napisałem test. Wykonałem go i ku mojemu zdziwieniu zakończył się on błędnie (tak, teraz pamiętam, to była chęć zaprezentowania tematu, a nie jego niezrozumienie ;-)). Do tej pory wszystkie testy wykonywałem z Apache OpenJPA i widząc efekt testu zacząłem podejrzewać błąd w implementacji. Postanowiłem to zweryfikować. Tylko jak?! Nie pozostało nic innego jak skorzystać z profili w Apache Maven 2 i zdefiniować trzy profile, odpowiadające poszczególnym dostawcom JPA. Po całodniowej walce w końcu się udało zestawić środowisko i dodatkowo je opisać. Okazało się również, że to, co mnie zaskoczyło, może być faktycznie błędem w OpenJPA, ponieważ uruchomienie dokładnie tego samego testu z Hibernate i TopLink kończy się pomyślnie (!) Wysłałem zapytanie na listę dyskusyjną OpenJPA-dev i oczekuję cierpliwie na odpowiedź.

Możliwość uruchamiania testów z wieloma dostawcami uzmysłowiła mi również braki w poszczególnych implementacjach specyfikacji JPA. Weźmy najpierw pod lupę Apache OpenJPA 0.9.7-SNAPSHOT. Do tej pory nie zauważyłem potencjalnie błędnego zachowania OpenJPA, aż do dnia dzisiejszego. Ważny jest jednak do zanotowania fakt, że jest to pierwsza wpadka OpenJPA. Z Hibernate EntityManager 3.3.0.GA jest znacznie, znacznie gorzej. Ot, weźmy jako przykład wsparcie dla adnotacji @NamedNativeQuery. Próba uruchomienia encji ze zdefiniowanym natywnym zapytaniem kończy się następującym błędem:

javax.persistence.PersistenceException: org.hibernate.cfg.NotYetImplementedException: Pure native scalar queries are not yet supported
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:258)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:120)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:83)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:60)
at pl.jaceklaskowski.jpa.chapter4_6.ConditionalExpressionsTest.setUp(ConditionalExpressionsTest.java:38)

Albo jeszcze inny błąd, a właściwie niezgodność ze specyfikacją JPA, na którą natrafiłem wykonując testy, które do tej pory pomyślnie wykonywałem z OpenJPA - numerowanie parametrów pozycyjnych. Wykonanie poniższego zapytania

SELECT DISTINCT o FROM Osoba o, IN(o.projekty) p WHERE p.rodzajProjektu = ?0

zgodnie ze specyfikacją - strona 90, gdzie napisano Input parameters are numbered starting from 1, powinno zakończyć się wyjątkiem (np. InvalidArgumentException) podczas, gdy jest akceptowane przez Hibernate. Dodatkowo, biorąc pod uwagę brak najnowszych wersji Hibernate w repozytoriach Maven 2, nie widzę powodów dla jego stosowania.

W przypadku TopLink Essentials 2.0 BUILD 40 sprawa jest najmniej kłopotliwa. Wszystko działa zgodnie z opisem w specyfikacji, co sugeruje, że chyba powinienem podmienić domyślny profil na toplink (patrz dzisiejszy artykuł).

Miłej lektury i poznawania JPA!