1. Обзор
В этом руководстве основное внимание будет уделено внедрению Spring Data JPA в проект Spring и полной настройке уровня сохраняемости. Пошаговое введение в настройку контекста Spring с использованием конфигурации на основе Java и базовой помпы Maven для проекта см . в этой статье .
2. Spring Data Generated DAO — больше никаких реализаций DAO
Как мы обсуждали в предыдущей статье, уровень DAO обычно состоит из большого количества шаблонного кода, который можно и нужно упростить. Преимуществ такого упрощения много: уменьшение количества артефактов, которые нам необходимо определить и поддерживать, согласованность шаблонов доступа к данным и согласованность конфигурации.
Spring Data делает еще один шаг вперед в этом упрощении и позволяет полностью удалить реализации DAO . Интерфейс DAO теперь является единственным артефактом, который нам нужно явно определить.
Чтобы начать использовать модель программирования Spring Data с JPA, интерфейс DAO должен расширить интерфейс репозитория , специфичный для JPA,
JpaRepository
. Это позволит Spring Data найти этот интерфейс и автоматически создать для него реализацию.
Расширяя интерфейс, мы получаем самые актуальные методы CRUD для стандартного доступа к данным, доступные в стандартном DAO.
3. Пользовательский метод доступа и запросы
Как уже говорилось, при реализации одного из интерфейсов репозитория
в DAO уже будут определены и реализованы некоторые базовые методы CRUD (и запросы) .
Чтобы определить более конкретные методы доступа, Spring JPA поддерживает довольно много параметров:
- просто определите новый метод в интерфейсе
- предоставить фактический запрос JPQL , используя аннотацию
@Query
- используйте более продвинутую поддержку спецификации и Querydsl в Spring Data
- определить пользовательские запросы через именованные запросы JPA
Третий вариант , Спецификации и поддержка Querydsl, похож на JPA Criteria, но использует более гибкий и удобный API. Это делает всю операцию более читабельной и многократно используемой. Преимущества этого API станут более заметными при работе с большим количеством фиксированных запросов, поскольку мы потенциально можем выразить их более кратко с помощью меньшего количества повторно используемых блоков.
Недостаток последнего варианта состоит в том, что он либо использует XML, либо обременяет доменный класс запросами.
3.1. Автоматические пользовательские запросы
Когда Spring Data создает новую реализацию Repository
, она анализирует все методы, определенные интерфейсами, и пытается автоматически сгенерировать запросы из имен методов . Хотя это имеет некоторые ограничения, это очень мощный и элегантный способ определения новых пользовательских методов доступа с минимальными усилиями.
Давайте посмотрим на пример. Если сущность имеет поле имени (и стандартные методы Java Bean
getName
и setName
), мы определим метод findByName
в интерфейсе DAO. Это автоматически сгенерирует правильный запрос:
public interface IFooDAO extends JpaRepository<Foo, Long> {
Foo findByName(String name);
}
Это относительно простой пример. Механизм создания запросов поддерживает гораздо больший набор ключевых слов .
Если синтаксический анализатор не может сопоставить свойство с полем объекта домена, мы увидим следующее исключение:
java.lang.IllegalArgumentException: No property nam found for type class com.foreach.spring.data.persistence.model.Foo
3.2. Пользовательские запросы вручную
Теперь давайте посмотрим на пользовательский запрос, который мы определим с помощью аннотации @Query
:
@Query("SELECT f FROM Foo f WHERE LOWER(f.name) = LOWER(:name)")
Foo retrieveByName(@Param("name") String name);
Для еще более детального контроля над созданием запросов, например, с использованием именованных параметров или изменением существующих запросов, рекомендуется начать со справочника.
4. Конфигурация транзакции
Фактическая реализация управляемого Spring DAO действительно скрыта, поскольку мы не работаем с ней напрямую. Однако это достаточно простая реализация SimpleJpaRepository ,
которая определяет семантику транзакций с помощью аннотаций .
Более явно, это использует аннотацию @Transactional
только для чтения на уровне класса, которая затем переопределяется для методов, не предназначенных только для чтения. Остальная семантика транзакций используется по умолчанию, но ее можно легко переопределить вручную для каждого метода.
4.1. Перевод исключений жив и здоров
Теперь возникает вопрос: поскольку Spring Data JPA не зависит от старых шаблонов ORM ( JpaTemplate
, HibernateTemplate
), и они были удалены с Spring 5, собираемся ли мы по-прежнему переводить наши исключения JPA в иерархию Spring DataAccessException
?
Ответ, конечно, мы. Преобразование исключений по-прежнему возможно при использовании аннотации @Repository
в DAO . Эта аннотация позволяет постпроцессору компонента Spring сообщать всем компонентам @Repository
все экземпляры PersistenceExceptionTranslator
, найденные в контейнере, и обеспечивать перевод исключений, как и раньше.
Давайте проверим перевод исключений с помощью интеграционного теста:
@Test(expected = DataIntegrityViolationException.class)
public void givenFooHasNoName_whenInvalidEntityIsCreated_thenDataException() {
service.create(new Foo());
}
Имейте в виду, что трансляция исключений выполняется через прокси. Чтобы Spring мог создавать прокси вокруг классов DAO, они не должны быть объявлены final
.
5. Конфигурация репозитория Spring Data JPA
Чтобы активировать поддержку репозитория Spring JPA, мы можем использовать аннотацию @EnableJpaRepositories
и указать пакет, содержащий интерфейсы DAO:
@EnableJpaRepositories(basePackages = "com.foreach.spring.data.persistence.repository")
public class PersistenceConfig {
...
}
Мы можем сделать то же самое с конфигурацией XML:
<jpa:repositories base-package="com.foreach.spring.data.persistence.repository" />
6. Конфигурация Java или XML
Мы уже подробно обсуждали, как настроить JPA в Spring в предыдущей статье. Spring Data также использует поддержку Spring для аннотации JPA @PersistenceContext
. Он использует это для подключения EntityManager
к фабричному компоненту Spring, ответственному за создание фактических реализаций DAO, JpaRepositoryFactoryBean
.
В дополнение к уже обсуждаемой конфигурации нам также необходимо включить XML-конфигурацию Spring Data, если мы используем XML:
@Configuration
@EnableTransactionManagement
@ImportResource("classpath*:*springDataConfig.xml")
public class PersistenceJPAConfig {
...
}
7. Зависимость от Maven
В дополнение к конфигурации Maven для JPA, как и в предыдущей статье , добавим зависимость spring-data-
jpa :
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
<version>2.4.0</version>
</dependency>
8. Использование Spring Boot
Мы также можем использовать JPA -зависимость Spring Boot Starter Data, которая автоматически настроит для нас DataSource .
Нам нужно убедиться, что база данных, которую мы хотим использовать, присутствует в пути к классам. В нашем примере мы добавили базу данных H2 в памяти:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>2.6.1</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.4.200</version>
</dependency>
В результате, просто выполняя эти зависимости, наше приложение запущено и работает, и мы можем использовать его для других операций с базой данных.
Явная конфигурация для стандартного приложения Spring теперь включена как часть автоматической настройки Spring Boot.
Конечно, мы можем изменить автоконфигурацию, добавив нашу настроенную явную конфигурацию.
Spring Boot предоставляет простой способ сделать это, используя свойства в файле application.properties .
Давайте посмотрим на пример изменения URL-адреса подключения и учетных данных:
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
9. Полезные инструменты для Spring Data JPA
Spring Data JPA поддерживается во всех основных средах разработки Java. Давайте посмотрим, какие полезные инструменты доступны для Eclipse и IntelliJ IDEA.
Если вы используете Eclipse в качестве IDE, вы можете установить подключаемый модуль Dali Java Persistence Tools . Это предоставляет диаграммы ER для сущностей JPA, генерацию DDL для инициализации схемы и основные возможности обратного проектирования. Кроме того, вы можете использовать Eclipse Spring Tool Suite (STS). Это поможет проверить имена методов запросов в репозиториях Spring Data JPA.
Если вы используете IntelliJ IDEA, есть два варианта.
IntelliJ IDEA Ultimate поддерживает диаграммы ER, консоль JPA для тестирования операторов JPQL и ценные проверки. Однако эти функции недоступны в Community Edition.
Чтобы повысить производительность в IntelliJ, вы можете установить подключаемый модуль JPA Buddy , который предоставляет множество функций, включая создание объектов JPA, репозиторий Spring Data JPA, DTO, сценарии инициализации DDL, миграцию версий Flyway, журналы изменений Liquibase и т. д. Кроме того, JPA Buddy предоставляет продвинутый инструмент для реверс-инжиниринга.
Наконец, плагин JPA Buddy работает как с версиями Community, так и с Ultimate.
10. Заключение
В этой статье мы рассмотрели настройку и реализацию уровня сохраняемости с помощью Spring 5, JPA 2 и Spring Data JPA (часть зонтичного проекта Spring Data) с использованием конфигурации на основе XML и Java.
Мы обсудили способы определения более сложных пользовательских запросов , а также семантику транзакций и конфигурацию с новым пространством имен jpa
. Конечным результатом является новый и элегантный подход к доступу к данным с помощью Spring, практически без реальной работы по реализации.
Реализацию этого туториала Spring Data JPA можно найти в проекте GitHub .