Tło

Blog

Porównanie wyciągania danych za pomocą JdbcTemplate a Spring Data JPA​

W tym porównaniu analizujemy dwa popularne podejścia do wyciągania danych z bazy danych w aplikacjach opartych na Spring. JdbcTemplate upraszcza tradycyjne podejście oparte na JDBC, umożliwiając łatwe wykonywanie zapytań SQL, podczas gdy Spring Data JPA korzysta z ORM (Object-Relational Mapping), automatyzując proces mapowania obiektów na tabele bazy danych. W zależności od wymagań aplikacji, każde z tych rozwiązań może być bardziej odpowiednie – JdbcTemplate sprawdzi się w prostych zapytaniach, a Spring Data JPA ułatwi zarządzanie bardziej złożonymi operacjami na danych Kod przedstawiający przykład użycia JdbcTemplate w Spring do pobierania danych z bazy danych. W tym przykładzie wykorzystujemy prostą konfigurację do wyciągania informacji z tabeli w relacyjnej bazie, co upraszcza proces integracji z bazą danych i redukuje ryzyko błędów w porównaniu do czystego JDBC
Ikona

W tym tutorialu porównamy dwie metody wyciągania danych z bazy danych, przy wykorzystaniu Frameworka Spring JPA a JdbcTemplate . Pierwsza metoda to JdbcTemplate, która upraszcza klasyczne użycie interfejsu JDBC. Druga to Spring Data JPA, które wykorzystuje podejście Object-Relational Mapping (ORM). Skupimy się na samej implementacji, pomijając szczegóły konfiguracji połączenia z serwerem bazy danych.

Wymagania

  • Java 8+
  • Maven
  • Spring

Zależność

Aby skorzystać z obu rozwiązań, użyjemy repozytorium Spring Boot. W tym tutorialu porównamy dwie metody wyciągania danych z bazy danych, wykorzystując Framework Spring. Pierwsza metoda to JdbcTemplate, która upraszcza klasyczne użycie interfejsu JDBC. Druga to Spring Data JPA, które stosuje podejście Object-Relational Mapping (ORM). Dla uproszczenia pominiemy konfigurację połączenia z serwerem bazy danych. Sprawdźmy JdbcTemplate a Spring JPA.

@Data
@AllArgsConstructor
@NoArgsConstructor
@Entity
public class Person {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String firstName;
    private String lastName;

    public Person(String firstName, String lastName) {
        this.firstName = firstName;
        this.lastName = lastName;
    }
}

Aby zredukować nadmiar kodu, wykorzystujemy adnotacje z biblioteki Lombok do automatycznego generowania getterów, setterów oraz konstruktorów. Dodatkowo, używamy adnotacji @Entity, @Id oraz @GeneratedValue, które są wykorzystywane przez ORM, o czym opowiemy później.

Wyciągnięcie danych za pomocą JdbcTemplate.

JdbcTemplate to interfejs, który upraszcza wykonywanie zapytań za pomocą klasycznego interfejsu JDBC. Pozwala również uniknąć typowych błędów, które mogą wystąpić przy korzystaniu z czystego JDBC. Dzięki JdbcTemplate nasz kod staje się bardziej zwięzły i przejrzysty.

Za pomocą JdbcTemplate spróbujemy wyciągnąć dane z tabeli Person. W tym celu musimy stworzyć zapytanie SQL oraz klasę mapującą rezultat zapytania na obiekt domenowy. Jeśli mielibyśmy więcej tabel i chcielibyśmy wyciągać dane z każdej z nich, dla każdej tabeli należałoby stworzyć osobną klasę mapującą. W naszym przykładzie stworzymy klasę mapującą dla relacji Person.

private final RowMapper<Person> personRowMapper = (rs, i) -> new Person(
rs.getLong("id"),
rs.getString("first_name"),
rs.getString("last_name")
);

Potrzebujemy również samo zapytanie, które w przykładzie chcemy żeby zwróciło wszystkie osoby z tabeli Person. Zapytanie jest bardzo proste i skonstruowane w SQL-u:

private static final String PG_FIND_ALL_PERSONS = "SELECT id, first_name, last_name FROM person";

Teraz można już stworzyć metodę zwracającą pożądany wynik:

public List<Person> findAll() {
    return jdbcTemplate.query(PG_FIND_ALL_PERSONS, personRowMapper);
}

Wyciąganięcie danych za pomocą Spring Data JPA

ORM (Object-Relational Mapping) to technika, która pozwala na odwzorowanie obiektów domenowych na tabele w relacyjnej bazie danych. Najpopularniejszą biblioteką ORM w Javie jest Hibernate, który został wykorzystany w tym tutorialu. Dodatkowo, Spring Data JPA to nakładka na technikę ORM, która znacząco upraszcza dostęp do danych. Główną zaletą tej biblioteki jest dostarczenie podstawowych operacji umożliwiających wyciąganie danych za pomocą interfejsów, które wystarczy rozszerzyć.

W przeciwieństwie do JdbcTemplate, w przypadku ORM wykorzystywane są wcześniej wspomniane adnotacje do mapowania relacji Person. Ponieważ klasę Person stworzyliśmy już wcześniej, teraz potrzebujemy tylko odpowiedniego repozytorium.

@Repository
public interface SprintDataJpaPersonRepository extends JpaRepository<Person, Long> {
}

Interfejs rozszerzamy o JpaRepository, gdzie wskazujemy Encję, której dotyczą nasze zapytania oraz klucz główny. To wystarczy, aby uzyskać gotowe metody do wszystkich operacji CRUD. Przykładem może być metoda List findAll(), która znajduje się w interfejsie JpaRepository. Dzięki temu, aby wyciągnąć wszystkie wpisy z tabeli Person, wystarczy wykorzystać tę gotową metodę. Poniżej znajduje się lista dostępnych metod z JpaRepository:

@NoRepositoryBean
public interface JpaRepository<T, ID> extends PagingAndSortingRepository<T, ID>, QueryByExampleExecutor<T> {
    List<T> findAll();

    List<T> findAll(Sort var1);

    List<T> findAllById(Iterable<ID> var1);

    <S extends T> List<S> saveAll(Iterable<S> var1);

    void flush();

    <S extends T> S saveAndFlush(S var1);

    void deleteInBatch(Iterable<T> var1);

    void deleteAllInBatch();

    T getOne(ID var1);

    <S extends T> List<S> findAll(Example<S> var1);

    <S extends T> List<S> findAll(Example<S> var1, Sort var2);
}

Podsumowanie JdbcTemplate a Spring JPA

Jeśli planujemy manipulować danymi w reprezentacji klas-relacja, zdecydowanie wygodniejszym rozwiązaniem będzie wykorzystanie ORM. Spring Data JPA przyspiesza proces budowania warstwy dostępu do danych, upraszczając wiele operacji. Z kolei, w przypadku gdy musimy stworzyć skomplikowane zapytanie i niekoniecznie potrzebujemy uzyskać reprezentację obiektową, JdbcTemplate może okazać się lepszym i wygodniejszym rozwiązaniem.

Projekt

Projekt dostępny pod adresem:
$ git clone git clone https://bitbucket.org/ptmsoft/ptm-blog.git