19 grudnia 2007

Ciekawostki JPA z XX spotkania Warszawa JUG

Podczas wczorajszego, XX spotkania grupy Warszawa JUG tematem przewodnim było Java Persistence API (JPA). Zajęliśmy się aktualizacją bazy danych przez dostawcę JPA o zmiany w encjach w trakcie trwania transakcji. Temat wcześniej opisałem w artykule Zasady zapisu zmian do bazy danych w JPA. Okazało się, że z 3 dostawców JPA - Apache OpenJPA, Hibernate EntityManager i TopLink Essentials, jedynie dwa ostatnie - Hibernate i TopLink działają tak samo, tzn. podczas pierwszego testu można zauważyć, że przed wykonaniem zapytania oba zapisują zmiany w bazie danych, a następnie wykonują zapytanie. W przypadku OpenJPA tak się nie dzieje. I tu możnaby zastanowić się, czy przypadkiem nie jest to błąd (!)

Piotr Tabor zauważył ciekawą rzecz, która unaocznia potencjalny problem z OpenJPA. Zmodyfikujmy zadanie o wyszukanie encji Osoba, których imię to Agata. Czego możemy spodziewać się od następującego fragmentu kodu?

System.out.println("\n=== Test #1: FlushModeType.AUTO z transakcja ===");

em.getTransaction().begin();
Osoba osoba = em.find(Osoba.class, osobaId);

System.out.println("\n>>> Zmieniamy imie osoby\n");
osoba.setImie("Agata");

System.out.println(">>> Wczytujemy wszystkie osoby\n");
Query query = em.createNamedQuery("Osoba.osobyPoImieniu");
query.setParameter("imie", "Agata");
List osoby = query.getResultList();
System.out.println("\n>>> Wszystkie osoby wczytane\n");

assert osoby.size() == 1 : "Liczba osób powinna być 1";
assert osoby.get(0).getImie().equals("Agata") : "Oczekujemy Agaty";

System.out.println(">>> Zatwierdzamy transakcje\n");
em.getTransaction().commit();

Czy oba warunki określone przez instrukcje assert powinny być spełnione? Z niecierpliwością czekam na odpowiedzi ;-) Zainteresowanych potyczkami z JPA zachęcam do skorzystania ze wspomnianego artykułu, w którym jest gotowe środowisko do odtworzenia sytuacji. Nie należy zapominać o stworzeniu zapytania nazwanego Osoba.osobyPoImieniu.