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!

4 komentarze:

  1. Witaj Jacku

    Nic się przed Tobą nie ukryje, nawet najdrobniejsza luka w implementacji ;-).

    Ten wyjątek to z tego co mi wiadomo to tylko brak implementacji danej adnotacji bo sam Hibernate wspiera natywne zapytania sql. Widziałem z resztą taska, który dokładnie ten problem porusza, niestety nie jest on narazie przypisany do konkretnej przyszłej wersji GA.

    Co do tej numeracji parametrów to faktycznie gafa, która może spowodować problemy z przenośnością kodu. Niemniej ja nigdy nie korzystam z parametrów numerowanych tylko z tych przypisanych do nazw. Moim zdaniem poprawia to o wiele czytelność kodu i chyba również trochę trudniej zrobić błąd ;-).

    PS. Świetne są te artykuły i wpisy w blogu, które tworzysz podczas lektury JPA spec. Tak dalej!

    Pozdrawiam,
    Rysiek

    OdpowiedzUsuń
  2. Nauka nauką, a przy okazji debugowanie implementacji :) Fajne zajecie.
    Swoja droga zastanawiam się skąd ty masz na to wszystko czas, dobe masz dłuższą czy nie śpisz? Ja żebym nie wiem jak chciał takiej wydajności nie jestem w stanie osiągnąć

    OdpowiedzUsuń
  3. Cześć mikeos!

    Skąd mam czas, pytasz?! Hmmm, nie mam i dlatego tak wolno idzie :P Zresztą sam spróbuj! Wystarczy być mocno ukierunkowanym na osiągnięcie określonego celu i tyle. Dodaj do tego moją pasję poznawania nowych technologii i masz odpowiedź. Akurat tak się składa, że znam wiele "mocnych" osób i na nich się wzoruję (spojrzyj na tych mocnych w Apache Geronimo i Apache OpenEJB - tam jest ich wielu - ja jestem w "ogonie").

    Muszę napisać coś w Notatniku, aby inni poznali sekret mojego braku czasu. Może zainspiruje to kolejnych do dzielenia się wiedzą i tym samym w krótszym czasie poznamy więcej, a to wierzę, że przełoży się na krótszy czas wdrażania projektów i więcej czasu dla nas (niekoniecznie, aby go zająć kolejnymi projektami ;-))

    A skoro są tacy, którym moje relacje się podobają pora napisać kolejną. A właśnie skończyłem! ;-)

    Jacek

    OdpowiedzUsuń
  4. Dołączam się do braw. Jacek, bomba! Dodam do tego jeszcze że Oracle ma plany otwarcia kodu (ang. open-source) TopLink'a. Szczegóły tutaj:

    http://www.oracle.com/corporate/press/2007_mar/OpenSource-TopLink.html?msgid=5512597

    OdpowiedzUsuń