Въведение в Spring Data JPA

1. Общ преглед

Тази статия ще се фокусира върху въвеждането на Spring Data JPA в проект Spring и изцяло конфигуриране на слоя за устойчивост. За стъпка по стъпка за въвеждане на контекста на Spring, използвайки Java-базирана конфигурация и основния Maven pom за проекта, вижте тази статия.

2. Пролетните данни, генерирани от 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 Named Queries

Третата опция - спецификациите и поддръжката на Querydsl - е подобна на критериите на JPA, но използва по-гъвкав и удобен API. Това прави цялата операция много по-четлива и многократна. Предимствата на този API ще станат по-изразени при работа с голям брой фиксирани заявки, тъй като потенциално бихме могли да ги изразим по-кратко чрез по-малък брой блокове за многократна употреба.

Тази последна опция има недостатъка, че включва или XML, или обременяване на класа на домейна с заявките.

3.1. Автоматични потребителски заявки

Когато Spring Data създава ново изпълнение на хранилището , той анализира всички методи, дефинирани от интерфейсите, и се опитва автоматично да генерира заявки от имената на методите . Въпреки че това има някои ограничения, това е много мощен и елегантен начин за дефиниране на нови персонализирани методи за достъп с много малко усилия.

Нека разгледаме един пример: ако обектът има поле с име (и стандартните методи на Java Bean getName и setName ), ще определим метода findByName в интерфейса DAO ; това автоматично ще генерира правилната заявка:

public interface IFooDAO extends JpaRepository { Foo findByName(String name); }

Това е относително прост пример. Механизмът за създаване на заявки поддържа много по-голям набор от ключови думи.

В случай, че анализаторът не може да свърже свойството с полето на обект на домейн, ще видим следното изключение:

java.lang.IllegalArgumentException: No property nam found for type class com.baeldung.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. Конфигурация на транзакцията

Действителното изпълнение на пролетно управлявания DAO наистина е скрито, тъй като не работим директно с него. Все пак, това е достатъчно проста реализация - на SimpleJpaRepository - който определя транзакционни семантика използвате пояснения .

По-изрично, това използва анотация @Transactional само за четене на ниво клас, която след това се заменя за методите, които не са само за четене. Останалата част от семантиката на транзакциите е по подразбиране, но те могат лесно да бъдат заменени ръчно за всеки метод.

4.1. Преводът на изключенията е жив и здрав

Въпросът е сега - тъй като Spring Data JPA не зависи от старите ORM шаблони ( JpaTemplate , HibernateTemplate ) и те са премахнати от пролетта 5 - все още ли ще получаваме нашите JPA изключения, преведени в йерархията DataAccessException на Spring ?

Разбира се, ние сме - преводът на изключения все още се активира чрез използването на анотацията @Repository в DAO . Тази анотация позволява на постпроцесора на Spring bean да съветва всички зърна @Repository с всички екземпляри на PersistenceExceptionTranslator, намерени в контейнера, и да предоставя превод на изключения, както преди.

Нека проверим превода на изключения с тест за интеграция:

@Test(expected = DataIntegrityViolationException.class) public void givenFooHasNoName_whenInvalidEntityIsCreated_thenDataException() { service.create(new Foo()); }

Имайте предвид, че преводът на изключения се извършва чрез прокси. За да може Spring да създаде проксита около DAO класовете, те не трябва да бъдат обявявани за окончателни .

5. Конфигурация на JPA хранилището на Spring Data

За да активираме поддръжката на JPA хранилище Spring, можем да използваме анотацията @EnableJpaRepositories и да посочим пакета, който съдържа DAO интерфейсите:

@EnableJpaRepositories(basePackages = "com.baeldung.spring.data.persistence.repository") public class PersistenceConfig { ... }

Можем да направим същото с XML конфигурация:

6. Java или XML конфигурация

Вече обсъдихме много подробно как да конфигурираме JPA през пролетта в предишна статия. Spring Data също се възползва от поддръжката на Spring за анотацията JPA @PersistenceContext . Той използва това, за да свърже EntityManager към фабричния боб Spring, отговорен за създаването на действителните реализации на DAO - JpaRepositoryFactoryBean .

В допълнение към вече обсъжданата конфигурация, ние също трябва да включим Spring Data XML Config - ако използваме XML:

@Configuration @EnableTransactionManagement @ImportResource("classpath*:*springDataConfig.xml") public class PersistenceJPAConfig { ... }

7. Зависимост на Maven

In addition to the Maven configuration for JPA, like in a previous article, we'll add the spring-data-jpa dependency:

 org.springframework.data spring-data-jpa 2.2.7.RELEASE 

8. Using Spring Boot

We can also use the Spring Boot Starter Data JPA dependency that will automatically configure the DataSource for us.

We also need to make sure that the database we want to use is present in the classpath. In our example, we've added the H2 in-memory database:

 org.springframework.boot spring-boot-starter-data-jpa 2.2.6.RELEASE   com.h2database h2 1.4.200 

As a result, just by doing these dependencies, our application is up and running and we can use it for other database operations.

The explicit configuration for a standard Spring application is now included as part of Spring Boot auto-configuration.

We can, of course, modify the auto-configuration by adding our customized explicit configuration.

Spring Boot provides an easy way to do this using properties in the application.properties file:

spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1 spring.datasource.username=sa spring.datasource.password=sa

In this example, we've changed the connection URL and credentials.

9. Conclusion

This article covered the configuration and implementation of the persistence layer with Spring 5, JPA 2, and Spring Data JPA (part of the Spring Data umbrella project), using both XML and Java-based configuration.

We discussed ways to define more advanced custom queries, as well as transactional semantics, and a configuration with the new jpa namespace. The final result is a new and elegant take on data access with Spring, with almost no actual implementation work.

Реализацията на този урок за JPA Spring Data може да бъде намерена в проекта GitHub.