JPA i Hibernate #7 - Read

JPA #7 – Read

Wkraczamy w drugą operację z rodziny CRUD, czyli przed nami Read. Zabieramy się zatem za odczyt zapisanych danych z bazy danych.

W celu odczytu danych z bazy danych musimy po pierwsze wyznaczyć po czym możemy odszukać taką daną.

Stworzymy w głównej klasie App szukanie po ID repo.findById() i tradycyjnie od razu dodamy tą metodę w GuestRepository.

Kod w klasie App wygląda tak:

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);
        System.out.println(guest.getId());
    }
}

Tworzymy metodę szukania danych

W GuestRepository tworzymy metodę findById() przyjmującą jeden paramter – long id. Użyjemy ponownie Entity Managera i jego metody find(). Trzeba wskazać dwa argumenty – klasę encji, którą będziemy wyszukiwać (w naszym wypadku Guest.class) i klucz główny (w naszym wypadku jest to 1).

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 Guest findById(long i) {
        System.out.println(" ------ FIND BY ID ------");
        return em.find(Guest.class, i);
    }
}

Na wyjściu dostaniemy odpowiednie ID, ale wciąż po odpaleniu aplikacji nie ma zapytania do bazy danych o nasz ID…

Entity Manager a wysyłanie zapytań do bazy danych

Entity Manager, jak wiemy, zarządza Persistence Context, w którym istnieje nasz obiekt. W momencie kiedy otrzymuje nasze zapytanie o wyszukanie ID gościa nie wysyła bezmyślnie tego zapytania dalej – kombinuje. Najpierw sprawdza czy posiada u siebie taki obiekt, który spełnia kryteria. W naszym wypadku tak jest. W związku z czym oszczędza czas na wysyłanie zapytania do bazy danych i czekania na jej odpowiedź. Sam jej udziela.

My, aby uzyskać takie zapytanie do bazy danych też pokombinujemy. W praktyce – cieszylibyśmy się z tej oszczędności czasu.

Uzyskanie zapytania do bazy danych

Oszukamy trochę i zmienimy kod.

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 Guest findById(long i) {
        System.out.println(" ------ FIND BY ID ------");
        em.clear();
        return em.find(Guest.class, i);
    }
}

Metoda em.clear() wyczyści nam cały Persistence Context. Dzięki temu wymuszamy zapytanie do bazy danych. Nie powinno się tak robić. Po to nasz Context służy za cache, by nie robić niepotrzebnych zapytań do bazy.

Zapytanie do bazy danych uzyskane dzięki użyciu em.clear() w zaznaczonym miejscu

Do odczytu danych nie potrzebujemy transakcji.

Gdy na podstawie danych z bazy danych chcemy stworzyć nowy obiekt to potrzebny jest konstruktor domyślny, czyli taki bez argumentów.

package pl.clockworkjava.hotelreservation.jpa;

import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class Guest {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private long id;

    private String name;
    private int age;

    public Guest() {
        
    }

    public Guest(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public long getId() {
        return this.id;
    }
}

Podsumowanie

Aby odczytać element z bazy danych nie potrzebujemy używać transakcji.

Jeśli obiekt, który spełnia kryteria naszego wyszukiwania znajduje się w Persistence Context to Entity Manager zwraca nam wartość bez wysłania zapytania do bazy danych.

Do utworzenia obiektu, na podstawie wyciągniętych z bazy danych, potrzebny jest domyślny konstruktor utworzony w klasie, która jest encją.

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.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *