1. Обзор
Хранимая процедура — это группа предопределенных операторов SQL, хранящихся в базе данных. В Java есть несколько способов доступа к хранимым процедурам. В этом руководстве мы узнаем, как вызывать хранимые процедуры из репозиториев Spring Data JPA.
2. Настройка проекта
Мы будем использовать JPA -модуль Spring Boot Starter Data в качестве уровня доступа к данным . Мы также будем использовать MySQL в качестве нашей серверной базы данных. Поэтому нам понадобятся зависимости Spring Data JPA , Spring Data JDBC и MySQL Connector в файле pom.xml
нашего проекта :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jdbc</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
Получив определение зависимости MySQL, мы можем настроить подключение к базе данных в файле application.properties :
spring.datasource.url=jdbc:mysql://localhost:3306/foreach
spring.datasource.username=foreach
spring.datasource.password=foreach
3. Класс сущности
В Spring Data JPA объект представляет собой таблицу, хранящуюся в базе данных. Следовательно, мы можем создать класс сущностей для сопоставления таблицы базы данных автомобилей :
@Entity
public class Car {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private long id;
@Column
private String model;
@Column
private Integer year;
// standard getters and setters
}
4. Создание хранимой процедуры
Хранимая процедура может иметь параметры , чтобы мы могли получать разные результаты в зависимости от ввода. Например, мы можем создать хранимую процедуру, которая принимает входной параметр целочисленного типа и возвращает список автомобилей:
CREATE PROCEDURE FIND_CARS_AFTER_YEAR(IN year_in INT)
BEGIN
SELECT * FROM car WHERE year >= year_in ORDER BY year;
END
Хранимая процедура также может использовать выходные параметры для возврата данных вызывающим приложениям. Например, мы можем создать хранимую процедуру, которая принимает входной параметр строкового типа и сохраняет результат запроса в выходной параметр:
CREATE PROCEDURE GET_TOTAL_CARS_BY_MODEL(IN model_in VARCHAR(50), OUT count_out INT)
BEGIN
SELECT COUNT(*) into count_out from car WHERE model = model_in;
END
5. Ссылка на хранимые процедуры в репозитории
В Spring Data JPA репозитории — это место, где мы предоставляем операции с базой данных. Мы можем создать репозиторий для операций базы данных с сущностью Car
и ссылаться на хранимые процедуры в этом репозитории:
@Repository
public interface CarRepository extends JpaRepository<Car, Integer> {
// ...
}
Далее давайте добавим в наш репозиторий несколько методов, которые вызывают хранимые процедуры.
5.1. Непосредственное сопоставление имени хранимой процедуры
Мы можем определить метод хранимой процедуры, используя аннотацию @Procedure
, и напрямую сопоставить имя хранимой процедуры.
Есть четыре эквивалентных способа сделать это. Например, мы можем использовать имя хранимой процедуры непосредственно в качестве имени метода:
@Procedure
int GET_TOTAL_CARS_BY_MODEL(String model);
Если мы хотим определить другое имя метода, мы можем поместить имя хранимой процедуры в качестве элемента аннотации @Procedure
:
@Procedure("GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModel(String model);
Мы также можем использовать атрибут procedureName
для сопоставления имени хранимой процедуры:
@Procedure(procedureName = "GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModelProcedureName(String model);
Наконец, мы можем использовать атрибут value
для отображения имени хранимой процедуры:
@Procedure(value = "GET_TOTAL_CARS_BY_MODEL")
int getTotalCarsByModelValue(String model);
5.2. Ссылка на хранимую процедуру, определенную в сущности
Мы также можем использовать аннотацию @NamedStoredProcedureQuery
для определения хранимой процедуры в классе сущностей:
@Entity
@NamedStoredProcedureQuery(name = "Car.getTotalCardsbyModelEntity",
procedureName = "GET_TOTAL_CARS_BY_MODEL", parameters = {
@StoredProcedureParameter(mode = ParameterMode.IN, name = "model_in", type = String.class),
@StoredProcedureParameter(mode = ParameterMode.OUT, name = "count_out", type = Integer.class)})
public class Car {
// class definition
}
Затем мы можем сослаться на это определение в репозитории:
@Procedure(name = "Car.getTotalCardsbyModelEntity")
int getTotalCarsByModelEntiy(@Param("model_in") String model);
Мы используем атрибут name
для ссылки на хранимую процедуру, определенную в классе сущностей. Для метода репозитория мы используем @Param
для соответствия входному параметру хранимой процедуры. Мы также сопоставляем выходной параметр хранимой процедуры с возвращаемым значением метода репозитория.
5.3. Ссылка на хранимую процедуру с аннотацией @Query
Мы также можем вызвать хранимую процедуру напрямую с помощью аннотации @Query
:
@Query(value = "CALL FIND_CARS_AFTER_YEAR(:year_in);", nativeQuery = true)
List<Car> findCarsAfterYear(@Param("year_in") Integer year_in);
В этом методе мы используем собственный запрос для вызова хранимой процедуры. Мы сохраняем запрос в атрибуте value аннотации.
Точно так же мы используем @Param
для соответствия входному параметру хранимой процедуры. Мы также сопоставляем выходные данные хранимой процедуры со списком объектов сущности Car
.
6. Резюме
В этой статье мы рассмотрели, как получить доступ к хранимым процедурам через репозитории JPA. Мы также обсудили два простых способа ссылки на хранимые процедуры в репозиториях JPA.
Как всегда, исходный код статьи доступен на GitHub .