JPA #8 – Update

Na warsztat trafia kolejna operacja z rodziny CRUD czyli Update – aktualizacja. Ponownie spotkamy się z wykorzystaniem transakcji i sprytnego zarządzania zapytaniami do bazy danych przez Entity Managera.

Na początek pamiętaj o usunięciu naszego małego tricku z poprzedniej lekcji, który kasuje dane w Persistence Context. Zatem z metody findById znika em.clear().

Update czyli aktualizacja danych gościa

Przenieśmy się do głównej klasy App i wprowadźmy kod, który będzie miał za zadanie umożliwienie aktualizacji danych gościa.

Zacznijmy od takiego kodu:

package pl.clockworkjava.hotelreservation.jpa;

public class App {

    public static void main(String[] args) {
        GuestRepository repo = new GuestRepository();
        repo.createNewGuest("Paweł", 34);
        Guest guest = repo.findById(1);
        repo.updateAge(guest, 35);
    }
}

Poprzez repozytorium zajmiemy się zmianą wieku gościa. W pierwszym argumencie przywołujemy naszego gościa, a w drugim nadajemy mu nowy wiek. Od razu tworzymy metodę w GuestRepository.

package pl.clockworkjava.hotelreservation.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class GuestRepository {

    private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("thePersistenceUnit");
    private static EntityManager em  = factory.createEntityManager();

    public void createNewGuest(String name, int age) {

        Guest newOne = new Guest(name, age);

        EntityTransaction transaction = em.getTransaction();

        transaction.begin();

        em.persist(newOne);

        transaction.commit();
    }

    public Guest findById(long i) {
        return em.find(Guest.class, i);
    }

    public void updateAge(Guest guest, int newAge) {

    }
}

Opakowanie procesów w transakcję

Jak w przypadku wprowadzania nowych danych, tak i w tym musimy skorzystać z transakcji. Dzięki temu, że zapis do bazy danych nastąpi dopiero po wykonaniu wszystkiego co sobie zaplanowaliśmy, unikniemy utraty danych lub błędnego zapisu wyniku naszych zmian.

W metodzie updateAge() rozpocznij transakcję. Dokładnie tak jak w przypadku create. Do aktualizacji wieku użyj guest.setAge(); i oczywiście stwórz do tego metodę. Dodatkowo jest jeszcze informacja o naszej czynności czyli tekst na konsoli.

Spróbuj, a później zerknij czy poniższy kod się zgadza.

package pl.clockworkjava.hotelreservation.jpa;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;

public class GuestRepository {

    private static EntityManagerFactory factory = Persistence.createEntityManagerFactory("thePersistenceUnit");
    private static EntityManager em  = factory.createEntityManager();

    public void createNewGuest(String name, int age) {

        Guest newOne = new Guest(name, age);

        EntityTransaction transaction = em.getTransaction();

        transaction.begin();

        em.persist(newOne);

        transaction.commit();
    }

    public Guest findById(long i) {
        return em.find(Guest.class, i);
    }

    public void updateAge(Guest guest, int newAge) {
        EntityTransaction transaction = em.getTransaction();
        System.out.println(" -------- UPDATE --------");
        transaction.begin();
        guest.setAge(newAge);
        transaction.commit();
    }
}

A daje to taki oto widok na konsoli:

 -------- UPDATE --------
Hibernate: /* update pl.clockworkjava.hotelreservation.jpa.Guest */ update Guest set age=?, name=? where id=?

Warto zauważyć, że zaktualizowane zostały wszystkie dane, a nie tylko te dotyczące wieku.

Natomiast, jeśli zmienimy nasz wiek na dokładnie taki sam repo.setAge(34)to będzie wypisane nic. Niepotrzebne zapytania do bazy danych tylko spowalniają działanie aplikacji także jest to bardzo dla nas korzystne, że najpierw sprawdzane jest co mamy w Persistence Context i jeśli finalnie nic się nie zmieniło nie wysyłamy żadnych dodatkowych zapytań do bazy.

Podsumowanie

W wypadku Update mamy do czynienia ze zmianą danych w bazie danych, a co za tym idzie musimy wykorzystać transakcję.

Aktualizacja danych jest wysyłana do bazy danych tylko w przypadku stwierdzenia różnicy między tym co jest aktualnie w Persistence Context a aktualnym stanem obiektu. Jest to korzystna oszczędność czasu.

Ponowny zapis danych obiektu dotyczy wszystkich jego danych, a nie tylko fragmentu, który zmieniliśmy.

Kod aplikacji znajdziesz w publicznym repozytorium GitHub.

By być na bieżąco i mieć realny wpływ na tematykę tworzonych artykułów zapraszam do dołączenia do mojego newslettera.


Informacje oparte zostały o materiał darmowego kursu wprowadzającego w świat JPA i Hibernate “Fundamenty JPA i Hibernate” dostępnego w formie wideo na platformie ClockworkJava.

Pozostałe artykuły z cyklu:

  1. Czym jest persystencja?
  2. ORM, JPA i Hibernate
  3. Podstawowe elementy
  4. Konfiguracja projektu
  5. Pierwsza encja
  6. Create
  7. Read
  8. Update
  9. Delete
  10. Relacja One-to-One
  11. Relacja One-to-Many

2 myśli w temacie “JPA #8 – Update”

  1. Cześć! Fajnie, że pokazałeś transakcję na praktycznym przykładzie. Polecam ze swojego doświadczenia adnotację Springa @Transactional, która pozwala nam nie mieszać kodu infrastruktury z logiką biznesową. Pozdrawiam!

    1. Dzięki za komentarz 🙂 Ano, Springowe @Transactional w wielu smakach czeka na swoją kolej 🙂

      Pozdrawiam, Paweł.

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *