Pokazywanie postów oznaczonych etykietą toplink. Pokaż wszystkie posty
Pokazywanie postów oznaczonych etykietą toplink. Pokaż wszystkie posty

16 grudnia 2007

Zasady zapisu zmian do bazy danych w JPA

0 komentarzy
Z każdym dniem na grupie pl.comp.lang.java pojawiają się coraz ciekawsze pytania i problemy związane z Java Persistence API (JPA) oraz Enterprise JavaBeans 3.0 (EJB3). Tym razem Marx zadał pytanie o zasady rządzące zapisem zmian encji do bazy danych w JPA - EJB3 - select robi update. W ten sposób sprowokował mnie do napisania kolejnego artykułu z serii przedstawiającej tajniki specyfikacji JPA - Zasady zapisu zmian do bazy danych w JPA.

Podobnie jak w poprzednich artykułach dotyczących JPA - Dynamiczny dostęp do wielu baz danych w JPA oraz Testowanie złączeń FETCH JOIN w JPA artykuł rozpoczyna się od przedstawienia teorii JPA, którą następnie zademonstrowałem w działaniu za pomocą aplikacji demonstracyjnej. Skorzystałem z konfiguracji projektu nadzorowanego przez Apache Maven 2, aby możliwe było uruchomienie go z 3-ma głównymi dostawcami JPA - Apache OpenJPA, Hibernate EntityManager oraz TopLink Essentials.

Drobnym acz ciekawym elementem konfiguracji Maven2 na potrzeby naszego projektu jest zależność javax.persistence.persistence-api, która występuje w wersji 1.0 w repozytorium Maven 2 oraz w wersji 1.0.2 w repozytorium Maven 1 na java.net. Biorąc pod uwagę, kto nadzoruje wersjami w repozytorium java.net (Sun) wydaje się być stosowne stosowanie bibliotek Korporacyjnej Javy właśnie z tego repozytorium. I tak też czynię w artykule.

27 marca 2007

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

4 komentarzy
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!