Статьи

Spring Data JPA Tutorial

Управление данными между java-классами или объектами и реляционной базой данных является очень громоздкой и сложной задачей. Уровень DAO обычно содержит много стандартного кода, который следует упростить, чтобы уменьшить количество строк кода и сделать код многократно используемым.

В этом уроке мы обсудим реализацию JPA для весенних данных.

1. Введение

1.1 Что такое JPA?

JPA или Java Persistence API — это спецификация Java для доступа, управления и сохранения данных между классами или объектами Java и реляционной базой данных. Спецификация была введена как часть EJB 3.0.

JPA — это не реализация или продукт, это просто спецификация. Он содержит множество интерфейсов, которые необходимо реализовать. Это структура, которая обеспечивает дополнительный уровень абстракции в реализации JPA. Слой репозитория будет содержать три слоя, как указано ниже.

  • Spring Data JPA: предоставляет интерфейсы репозитория данных Spring, которые реализованы для создания репозиториев JPA.
  • Spring Data Commons: — Обеспечивает инфраструктуру, которая используется совместно для конкретных проектов данных Spring.
  • Поставщик JPA, который реализует постоянный API JPA.

Spring data JPA позволяет нам не писать никакого стандартного кода, добавляя дополнительный слой хранилища.

1.2 История JPA

JPA2.0: — Разработка JPA2.0 началась в 2007 году как JSR 317. Версия была помечена как 2.0, поскольку она не смогла получить общее согласие для 1.0. Основное внимание было уделено функциям, доступным как часть известных поставщиков ORM.

JPA 2.1: — JPA2.1 был запущен в июле 2011 года как JSR 338. Некоторые из основных функций: граф сущностей, хранимые процедуры, преобразователи и т. Д.

JPA 2.2: — JPA2.2 — последнее дополнение к серии JPA в 2017 году. Оно включает поддержку даты и времени в Java 8, возможность потоковой передачи результатов запроса.

JPA все еще претерпевает много изменений, и мы можем ожидать более новую версию JPA в ближайшее время.

1.3 Spring Data Repositories

Проект Spring Data Commons предоставляет абстракцию хранилища, которая расширяется подпроектами, специфичными для хранилища данных.

Мы должны быть знакомы с интерфейсами репозитория Spring Data, так как это поможет нам в реализации интерфейсов. Давайте посмотрим на интерфейсы.

Spring Data Commons: — В рамках этого проекта предусмотрены следующие интерфейсы:

  • Repository<T, ID extends Serializable> : этот интерфейс является интерфейсом маркера.
    1. Он фиксирует тип управляемого объекта и тип идентификатора объекта.
    2. Это помогает контейнеру Spring обнаруживать «конкретные» интерфейсы репозитория при сканировании classpath.
  • CrudRepository<T, ID extends Serializable> : предоставляет операции CRUD для управляемого объекта.
  • PagingAndSortingRepository<T, ID extends Serializable> : этот интерфейс объявляет методы, используемые для сортировки и разбивки на страницы объектов, извлекаемых из базы данных.
  • QueryDslPredicateExecutor<T> : это не «интерфейс репозитория». Он объявляет методы, которые используются для извлечения сущностей из базы данных с использованием QueryDsl предиката QueryDsl .

Spring Data JPA: — Этот проект предоставляет следующие интерфейсы:

  • JpaRepository<T, ID extends Serializable> : этот интерфейс является специфичным для JPA интерфейсом репозитория, который объединяет методы, объявленные общими интерфейсами репозитория за одним интерфейсом.
  • JpaSpecificationExecutor<T> : это снова не «интерфейс репозитория». Он объявляет методы, которые используются для извлечения сущностей из базы данных с использованием объектов Specification<T> которые используют API критериев JPA.

Иерархия хранилища выглядит следующим образом:

Иерархия репозитория данных Spring

Давайте попробуем разобраться в Spring Data JPA через пример программы.

1.4 Пользовательский запрос данных Spring

Давайте рассмотрим случай использования, когда мы должны получать данные из базы данных на основе запроса. Написание пользовательского запроса — очень полезный случай. Spring Data JPA имеет разные способы написания пользовательских запросов. Мы будем широко классифицировать пути, как указано ниже.

Автоматические пользовательские запросы . Автоматическое создание пользовательских запросов также называется созданием запросов из имени метода. Spring Data JPA имеет встроенный механизм создания запросов, который можно использовать для анализа запросов прямо из имени метода метода запроса. Механизм сначала удаляет общие префиксы из имени метода и анализирует ограничения запроса из остальной части имени метода. Чтобы использовать этот подход, мы должны убедиться, что имена методов вашего интерфейса репозитория созданы путем объединения имен свойств объекта сущности и поддерживаемых ключевых слов.

Преимущество использования этого подхода состоит в том, что он очень прост в реализации. Но ограничение состоит в том, что если запрос содержит более одного параметра, имя метода будет недоступно для чтения. Также ключевые слова, которые не поддерживаются JPA, например, более низкие, не будут полезны при таком подходе.

Ручные пользовательские запросы: Ручные пользовательские запросы также известны как создание запросов с использованием тега @Query . Аннотация @Query будет использоваться для создания запросов с использованием языка запросов JPA и для привязки этих запросов непосредственно к методам интерфейса вашего репозитория. Когда вызывается метод запроса, Spring Data JPA выполнит запрос, указанный в аннотации @Query .

Преимущество этого подхода в том, что вы можете использовать язык запросов JPA для создания запроса. Кроме того, запрос остается на уровне хранилища. Ограничением этого подхода является то, что @Query может использоваться только тогда, когда поддерживается язык запросов JPA.

Программа, упомянутая ниже, использует оба подхода.

1.5 Spring Data JPA Перевод исключений

Следует учесть, что шаблоны Spring ORM по умолчанию не используются с SPring JPA. Не теряем ли мы трансляцию исключений с помощью Spring Data JPA? Не собираемся ли переводить исключения JPA в иерархию SpringAA DataException?

Ответ — нет . @Repository исключений по-прежнему включено с помощью аннотации @Repository в DAO. Аннотация позволяет постпроцессору bean-компонента Spring @Repository всем @Repository компонентам @Repository всех экземплярах PersistenceExceptionTranslator найденных в контейнере, и обеспечивает преобразование исключений, как и раньше.

2. Инструменты и технологии

Давайте посмотрим на технологии и инструменты, используемые для создания программы.

  • Eclipse Oxygen.2 Release (4.7.2)
  • Java — версия 9.0.4
  • Maven — 3,5,3
  • Spring boot — 2.0.1-Release
  • Postgresql — 10
  • почтальон

3. Структура проекта

Структура нашего проекта будет выглядеть так, как показано на рисунке ниже.

Структура проекта для учебника JPA по Spring Data

Приведенная выше структура проекта использует Maven. Этот проект также можно создать с помощью Gradle, и файл pom.xml будет заменен файлом build.gradle. Структура проекта будет немного зависеть от использования Gradle для сборки.

4. Цель Программы

В рамках программы мы попытаемся создать простой веб-сервис с использованием весенней загрузки. Этот веб-сервис будет использоваться для манипулирования данными в базе данных PostgreSQL.

4.1 pom.xml

Файл pom.xml для программы будет выглядеть так, как указано ниже.

pom.xml для SpringData JPA с Spring Boot

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
<?xml version="1.0" encoding="UTF-8"?>
    <modelVersion>4.0.0</modelVersion>
 
    <groupId>com.springjpa</groupId>
    <artifactId>SpringJPA-PostgreSQL</artifactId>
    <version>0.0.1</version>
    <packaging>jar</packaging>
 
    <name>SpringJPA-PostgreSQL</name>
    <description>Demo project for Spring Boot JPA - PostgreSQL</description>
 
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.1.RELEASE</version>
        <relativePath/>
    </parent>
 
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.9</java.version>
    </properties>
 
    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.postgresql</groupId>
            <artifactId>postgresql</artifactId>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
  <groupId>javax.xml.bind</groupId>
  <artifactId>jaxb-api</artifactId>
  <version>2.3.0</version>
</dependency>
    </dependencies>
 
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
     
 
 
</project>

Файл pom.xml будет содержать зависимости, которые понадобятся как часть программы.

4.2 Класс применения

Класс Application.java для нас — SpringJpaPostgreSqlApplication.java класс SpringJpaPostgreSqlApplication.java . Класс выглядит так, как показано ниже.

SpringJpaPostgreSqlApplication.java класс для Spring Boot

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.tutorial;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
 
import com.tutorial.repo.EmployeeRepository;
 
@SpringBootApplication
public class SpringJpaPostgreSqlApplication implements CommandLineRunner{
 
    @Autowired
    EmployeeRepository repository;
     
    public static void main(String[] args){
        SpringApplication.run(SpringJpaPostgreSqlApplication.class, args);
    }
 
    public void run(String... args) throws Exception {
        // TODO Auto-generated method stub
         
    }
 
}

Интерфейс CommandLineRunner используется для указания того, что компонент должен запускаться, когда он содержится в приложении Spring.

4.3 Модельный класс

Мы собираемся создать класс Employee.java как класс модели. Класс будет выглядеть так, как показано ниже.

Модельный класс для программы

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
package com.tutorial.model;
 
import java.io.Serializable;
 
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
 
@Entity
@Table(name = "employee")
public class Employee implements Serializable {
 
    private static final long serialVersionUID = -3009157732242241606L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id")
    private long id;
 
    @Column(name = "firstname")
    private String firstName;
 
    @Column(name = "lastname")
    private String lastName;
     
    @Column(name = "age")
    private int age;
 
    protected Employee() {
    }
 
    public Employee(String firstName, String lastName,int age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
 
    @Override
    public String toString() {
        return String.format("Employee[id=%d, firstName='%s', lastName='%s', age='%d']", id, firstName, lastName,age);
    }
 
     
    public long getId() {
        return id;
    }
 
    public void setId(long id) {
        this.id = id;
    }
 
    public String getFirstName() {
        return firstName;
    }
 
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }
 
    public String getLastName() {
        return lastName;
    }
 
    public void setLast_Name(String lastName) {
        this.lastName = lastName;
    }
 
    public int getAge() {
        return age;
    }
 
    public void setAge(int age) {
        this.age = age;
    }
}

@Entity : используется для определения того, что класс является классом Entity.
@Table : эта аннотация используется для указания имени таблицы, определенной в базе данных.
@Id : аннотация Id используется для указания атрибута Id
@GeneratedValue : используется, когда мы хотим установить автоматически сгенерированное значение. GenerationType — это механизм, который используется для генерации значения для определенного столбца.
@Column : эта аннотация используется для сопоставления столбцов таблицы с атрибутами в классе.

4.4 Интерфейс репозитория

Интерфейс репозитория используется для расширения интерфейса CRUD. Этот интерфейс добавляет слой репозитория в программу. Spring Data JPA предоставляет два основных способа создания запросов. Эти запросы затем используются в интерфейсе хранилища для извлечения данных из базы данных.

Класс репозитория для расширения репозитория CRUD

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
package com.tutorial.repo;
 
import java.util.List;
 
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
 
import com.tutorial.model.Employee;
 
@Repository
public interface EmployeeRepository extends CrudRepository<Employee, Long>{
    List findByLastName(String lastName);
     
@Query("SELECT e FROM Employee e WHERE e.age = :age")
    public List findByAge(@Param("age") int age);
}

CrudRepository — это интерфейс из проекта SpringData Common. Два упомянутых выше метода для создания запроса используются в следующих местах кода.

Автоматический пользовательский запрос:

1
List findByLastName(String lastName);

Метод findByLastName содержит фамилию в качестве параметра, который будет использоваться для поиска данных. Кроме того, запрос будет автоматически создан с использованием построителя запросов JPA.

Ручной пользовательский запрос:

1
2
@Query("SELECT e FROM Employee e WHERE e.age = :age")
   public List findByAge(@Param("age") int age);

В этом методе мы вручную определили запрос для выборки данных по возрасту, а затем запрос был связан с методом findByAge .

4.5 Файл свойств

В рамках весенней загрузки для подключения к базе данных мы предоставим детали в файле свойств. Файл свойств будет выглядеть так, как показано ниже.

файл application.properties для весенней загрузки

1
2
3
4
5
6
spring.datasource.url=jdbc:postgresql://localhost:5432/postgres
spring.datasource.username=postgres
spring.datasource.password=password
spring.jpa.generate-ddl=true
spring.jpa.show-sql=true
spring.jpa.properties.hibernate.format_sql=true

Как часть файла свойств, предоставляются URL базы данных и учетные данные. Свойство spring.jpa.show-sql=true показывает запрос SQL, сгенерированный во время обработки данных JPA.

4.6 Класс контроллера

Контроллер является наиболее важным классом всей программы. Это класс, отвечающий за все отображение URL. Мы добавили методы репозитория для манипулирования данными в этом классе.

Класс контроллера для программы

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
package com.tutorial.controller;
 
import java.util.List;
import java.util.Optional;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import com.tutorial.model.Employee;
import com.tutorial.repo.EmployeeRepository;
 
@RestController
@RequestMapping("/employee")
public class WebController {
    @Autowired
    EmployeeRepository repository;
     
    @RequestMapping(value="/save",method = RequestMethod.POST)
    public HttpStatus insertEmployee(@RequestBody Employee employee){
        boolean status = repository.save(employee) != null;    
        return status? HttpStatus.CREATED : HttpStatus.BAD_REQUEST;
    }
     
     
    @RequestMapping("/findall")
    public List findAll(){
         
         
        return (List) repository.findAll();
    }
     
    @RequestMapping("/findbyid")
    public Optional findById(@RequestParam("id") long id){
        Optional result = repository.findById(id);
        return result;
    }
     
    @RequestMapping("/findbylastname")
    public List fetchDataByLastName(@RequestParam("lastname") String lastName){
                 
        return repository.findByLastName(lastName);
    }
    @RequestMapping("/findbyage")
    public List fetchDataByAge(@RequestParam("age") int age){
                 
        return repository.findByAge(age);
    }
}

Тег @RestController используется для определения класса как класса контроллера покоя.
Тег @RequestMapping указывает отображение пути для запроса. Атрибут Value задает сопоставление URL, а атрибуты метода — тип метода, например GET, POST, PUT и т. Д.
Если мы не указываем атрибут метода по умолчанию, метод считается методом GET.

В этом классе мы автоматически подключили хранилище и используем методы, доступные в интерфейсе для извлечения, вставки и удаления данных.

Для запуска приложения весенней загрузки мы должны предоставить команду spring-boot: run .

5. Выход

Приведенные ниже запросы могут быть использованы для создания таблицы Employee в PostgreSQL.

SQL-запрос для создания таблицы Employee

1
2
3
4
5
6
create table employee (
id serial not null primary key,
firstName varchar(20) not null,
lastName varchar(20) not null,
age integer not null
);

Позволяет нам проверить данные, доступные в базе данных. Текущие данные, доступные в базе данных, показаны ниже.

Данные в PostgreSQL

Теперь давайте попробуем API findall, используя коллекцию почтальонов, чтобы получить строки в качестве результата. Результат будет выглядеть, как показано ниже на почтальоне.

Результат API findall на почтальоне

Для того, чтобы добавить некоторый объект сотрудника в базу данных. Мы будем использовать API сохранения и передадим объект сотрудника.

Хранение объектов в БД с API сохранения

Давайте проверим базу данных после использования API сохранения. База данных будет выглядеть так, как показано ниже.

После сохранения данных с помощью Save API

Точно так же мы можем использовать API findbylastname для поиска записей с фамилией, указанной в параметре запроса.

Результат API findbylastname

Давайте посмотрим результат для метода, который связан с пользовательским запросом вручную.

Результат API findByAge

6. Резюме

Краткое содержание урока упоминается ниже.

  1. SpringData JPA предоставляет абстракцию репозитория, которая используется для API персистентности JPA.
  2. Мы узнали об использовании CRUD-репозитория.
  3. Мы использовали автоматические пользовательские запросы для поиска строк по фамилии.
  4. Мы узнали о ручном создании пользовательских запросов.
  5. Преобразование исключений JPA зависит от тега @Repository .

7. Скачать проект Eclipse

Это было руководство для SpringData JPA с SpringBoot.

Вы можете скачать полный исходный код этого примера здесь: SpringJPA-PostgreSQL.zip