Przejdź do treści
Tło

Blog

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

Ikona

W dzisiejszym tutorialu zaprezentujemy porównanie metod wyciągania danych z bazy danych porównując dwa podejścia. W obydwu przypadkach wykorzystamy Framework Spring’a. W pierwszym przypadku użyjemy klasy JdbcTemplate, która upraszcza klasyczny sposób wykorzystania interfejsu JDBC. W drugim zaprezentujemy wykorzystanie Object-Relational Mapping (ORM) z wykorzystaniem biblioteki Spring Data JPA. Na potrzeby tutorialu pominiemy konfigurację połączenia z serwerem bazy danych.

Wymagania

  • Java 8+
  • Maven
  • Spring

Zależność

Aby móc skorzystać z obydwu rozwiązań skorzystamy z repozytorium SpringBoot:

W dzisiejszym tutorialu zaprezentujemy porównanie metod wyciągania danych z bazy danych porównując dwa podejścia. W obydwu przypadkach wykorzystamy Framework Spring’a. W pierwszym przypadku użyjemy klasy JdbcTemplate, która upraszcza klasyczny sposób wykorzystania interfejsu JDBC. W drugim zaprezentujemy wykorzystanie Object-Relational Mapping (ORM) z wykorzystaniem biblioteki Spring Data JPA. Na potrzeby tutorialu pominiemy konfigurację połączenia z serwerem bazy danych.
@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ć nadmierną liczbę kodu, wykorzystujemy annotacje z biblioteki lombok do generowania getterów oraz setterów jak również konstruktorów. Widać również annotacje @Entity, @Id oraz @GeneratedValue – wykorzystywane przez ORM o czym później.

W przypadku wykorzystania jdbcTemplate wszystkie annotacje z pakietu javax.persistence są zbędne.

Wyciągnięcie danych za pomocą JdbcTemplate

JdbcTemplate jest interfejsem upraszczającym wykonywanie zapytań za pomocą interfejsu JDBC. Dodatkowo pozwala wyeliminować podstawowe błędy przy wykorzystaniu czystego JDBC. Dzięki użyciu JdbcTemplate nasz kod jest bardziej zwięzły i przejrzysty.
Za pomocą JdbcTemplate, spróbujemy wyciągnąć dane z tabeli person. Potrzebujemy stworzyć do tego zapytanie SQL, oraz klasę mapującą rezultat zapytania do obiektu domenowego. Jeśli mielibyśmy wiele tabel i z każdej z nich chcielibyśmy wyciągać dane, do każdej tabeli osobno trzeba by tworzyć klasę mapującą. W naszym przykładzie musimy stworzyć 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 jest to technika służąca do odwzorowania obiektów domenowych na tabele relacyjnej bazy danych. Najpopularniejszą biblioteką ORM w Javie jest Hibernate, który został wykorzystany w tym tutorialu. Biblioteka Spring Data JPA jest dodatkową nakładką na technikę ORM, która ułatwia nam dostęp do danych. Główną jej zaletą jest dostarczenie podstawowych operacji do wyciągania danych za pomocą interfejsów, które wystarczy rozszerzyć.
W przeciwieństwie do JdbcTemplate w przypadku ORM wykorzystywane są wspomniane wcześniej annotacje do zmapowania relacji person. Ponieważ klasę Person stworzyliśmy już wcześniej, teraz potrzebujemy tylko Repozytorium:
@Repository
public interface SprintDataJpaPersonRepository extends JpaRepository<Person, Long> {
}

Interfejs rozszerzamy o JpaRepository, gdzie wskazujemy Encję której mają dotyczyć nasze query oraz klucz główny. To wystarczy do tego, żeby dysponować gotowymi metodami do wszystkich operacji CRUD i tak przykładowo metoda List findAll() znajduje się w interfejsie JpaRepository tak więc do wyciągnięcia wszystkich wpisów z tabeli person wystarczy wykorzystać gotową już metodę. Lista dostępnych metod z JpaRepository znajduje się poniżej:

@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

Jeśli zamierzamy manipulować na danych w reprezentacji klas-relacja to zdecydowanie wygodniejszym sposobem jest wykorzystanie ORM. Wykorzystanie biblioteki Spring Data JPA przyśpiesza nam proces budowania warstwy dostępu do danych. W sytuacji w której potrzebujemy stworzyć skomplikowane zapytanie i niekoniecznie potrzebujemy potem 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