5. Вступ до Spring Data JPA
У цьому розділі ми розглянемо таку архітектуру:
![]() |
Між рівнем [DAO] та драйвером JDBC модуля SGBD вставляється рівень [JPA] (Java Persistence API). Відтепер саме рівень JPA надсилає команди SQL, призначені для SGBD. Рівень [DAO] більше не обробляє команди SQL, а лише об’єкти, які називаються сутностями JPA і є відображеннями різних таблиць використовуваної бази даних. Поля цих сутностей однозначно пов’язані зі стовпцями таблиць за допомогою анотацій Java. Саме це дозволяє шару JPA перетворювати в SQL операції шару [DAO], що виконуються над сутностями JPA.
Spring Data — це гілка Spring, що займається доступом до даних, незалежно від того, чи зберігаються вони в реляційній базі даних SGBDR, базі NOSQL чи в інших типах сховищ. Тут нас цікавлять лише SGBDR та доступ до них через JPA. Надалі ми іноді будемо писати [Spring JPA], маючи на увазі насправді [Spring Data JPA]. У наведеній вище архітектурі рівень [Spring Data] надає рівню [DAO] засоби для управління об’єктами JPA.
JPA — це, по суті, специфікація. Ми протестуємо три її реалізації:
- Hibernate (http://hibernate.org/);
- EclipseLink (http://www.eclipse.org/eclipselink/);
- OpenJpa (http://openjpa.apache.org/);
5.1. Exemple-01
На сайті Spring є багато підручників для початківців із Spring [http://spring.io/guides]. Ми скористаємося одним із них, щоб ознайомитися зі Spring Data. Для цього ми використовуємо Spring Tool Suite (STS).
![]() |
- у [1] ми імпортуємо один із підручників із [spring.io/guides];
![]() |
- у [2] вибираємо підручник [Accessing Data Jpa], який демонструє, як отримати доступ до бази даних за допомогою Spring Data;
- у [3] вибираємо проект, налаштований за допомогою Maven;
- у [4] підручник може бути наданий у двох формах: [initial] — це порожня версія, яку заповнюють, слідуючи підручнику, або [complete] — це остаточна версія підручника. Ми обираємо останню;
- у [5] можна переглянути посібник у браузері;
- у [6] — кінцевий проект.
5.1.1. Налаштування Maven для проекту
Залежності Maven для проекту налаштовуються у файлі [pom.xml]:
<groupId>org.springframework</groupId>
<artifactId>gs-accessing-data-jpa</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
</dependencies>
<properties>
<!-- використовувати UTF-8 для всього -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<start-class>hello.Application</start-class>
</properties>
- рядки 5–9: визначають батьківський проект Maven. Саме він визначає основну частину залежностей проекту. Їх може бути достатньо, і в цьому випадку додаткові залежності не додаються, або ж їх може не вистачати, і в цьому випадку додаються відсутні залежності;
- рядки 12–15: визначають залежність від [spring-boot-starter-data-jpa]. Цей артефакт містить класи Spring Data;
- рядки 16–19: визначають залежність від SGBD та H2, що дозволяє створювати та керувати базами даних у пам’яті.
Розглянемо класи, що надаються цими залежностями:
![]() | ![]() | ![]() |
Їх дуже багато:
- деякі належать до екосистеми Spring (ті, що починаються з spring);
- інші належать до екосистеми Hibernate (hibernate, jboss), реалізацію якої ми тут використовуємо — JPA;
- ще інші — це бібліотеки тестів (junit, hamcrest);
- ще інші — бібліотеки логів (log4j, logback, slf4j);
Ми збережемо їх усі. Для додатка, що працює у виробничому середовищі, слід залишити лише ті, що є необхідними.
У рядку 26 файлу [pom.xml] міститься такий рядок:
<start-class>hello.Application</start-class>
Цей рядок пов’язаний із такими рядками:
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
У рядках 6–9 плагін [spring-boot-maven-plugin] дозволяє згенерувати виконуваний JAR-файл додатка. Рядок 26 файлу [pom.xml] позначає виконуваний клас цього JAR-файлу.
5.1.2. Рівень [JPA]
Доступ до бази даних здійснюється через шар [JPA], Java Persistence API:
![]() |
![]() |
Додаток є базовим і обслуговує клієнтів [Customer]. Клас [Customer] входить до складу шару [JPA] і має такий вигляд:
package hello;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
protected Customer() {
}
public Customer(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
@Override
public String toString() {
return String.format("Customer[id=%d, firstName='%s', lastName='%s']", id, firstName, lastName);
}
}
Клієнт має ідентифікатор [id], ім’я [firstName] та прізвище [lastName]. Кожен екземпляр [Customer] представляє рядок таблиці бази даних.
- рядок 8: анотація JPA, яка визначає, що збереження екземплярів [Customer] (Create, Read, Update, Delete) буде здійснюватися за допомогою реалізації JPA. Згідно з залежностями Maven, бачимо, що використовується реалізація JPA / Hibernate;
- рядки 11–12: анотації JPA, які пов’язують поле [id] із первинним ключем таблиці [Customer]. Рядок 12 вказує, що реалізація JPA використовуватиме метод генерації первинного ключа, властивий використовуваному SGBD, у даному випадку H2;
Інших анотацій JPA немає. У такому разі будуть використані значення за замовчуванням:
- таблиця [Customer] матиме назву класу, тобто [Customer];
- стовпці цієї таблиці матимуть назви полів класу: [id, firstName, lastName], враховуючи, що у назві стовпця таблиці не враховується регістр;
Слід зауважити, що використовувана реалізація JPA ніде не називається.
5.1.3. Рівень [Spring Data]
Клас [CustomerRepository] реалізує рівень доступу до таблиці [Customer]. Його код такий:
![]() |
![]() |
package hello;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
Отже, це інтерфейс, а не клас (рядок 7). Він розширює інтерфейс [CrudRepository], інтерфейс Spring Data (рядок 5). Цей інтерфейс має два параметри: перший — тип елементів, що обробляються (у даному випадку тип [Customer]), другий — тип первинного ключа цих елементів (у даному випадку тип [Long]). Інтерфейс [CrudRepository] має такий вигляд:
package org.springframework.data.repository;
import java.io.Serializable;
@NoRepositoryBean
public interface CrudRepository<T, ID extends Serializable> extends Repository<T, ID> {
<S extends T> S save(S entity);
<S extends T> Iterable<S> save(Iterable<S> entities);
T findOne(ID id);
boolean exists(ID id);
Iterable<T> findAll();
Iterable<T> findAll(Iterable<ID> ids);
long count();
void delete(ID id);
void delete(T entity);
void delete(Iterable<? extends T> entities);
void deleteAll();
}
Цей інтерфейс визначає операції CRUD (Create – Read – Update – Delete), які можна виконувати над типом JPA T:
- рядок 8: метод save дозволяє зберегти суть T у базі даних. Він зберігає суть із первинним ключем, який їй присвоїв SGBD. Він також дозволяє оновити суть T, ідентифіковану за її первинним ключем id. Вибір тієї чи іншої дії залежить від значення первинного ключа id: якщо його значення дорівнює null, виконується операція збереження, в іншому випадку — операція оновлення;
- рядок 10: те саме, але для списку сутностей;
- рядок 12: метод findOne дозволяє знайти суть T, ідентифіковану за її первинним ключем id;
- рядок 22: метод delete дозволяє видалити суть T, ідентифіковану за її первинним ключем id;
- рядки 24–28: варіанти методу [delete];
- рядок 16: метод [findAll] дозволяє знайти всі збережені сутності T;
- рядок 18: те саме, але обмежено сутностями, для яких передано список ідентифікаторів;
Повернемося до інтерфейсу [CustomerRepository]:
package hello;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
public interface CustomerRepository extends CrudRepository<Customer, Long> {
List<Customer> findByLastName(String lastName);
}
- рядок 9 дозволяє знайти [Customer] за його назвою [lastName];
І це все щодо шару [DAO]. Класу реалізації попереднього інтерфейсу немає. Він генерується під час виконання за допомогою [Spring Data]. Методи інтерфейсу [CrudRepository] реалізуються автоматично. Щодо методів, доданих до інтерфейсу [CustomerRepository], то тут все залежить від конкретного випадку. Повернемося до визначення [Customer]:
private long id;
private String firstName;
private String lastName;
Метод у рядку 9 реалізується автоматично класом [Spring Data], оскільки він посилається на поле [lastName] (рядок 3) класу [Customer]. Коли Spring Data зустрічає метод [findBySomething] в інтерфейсі, що підлягає реалізації, він реалізує його за допомогою такого запиту JPQL (Java Persistence Query Language):
Отже, тип T повинен мати поле з іменем [something]. Таким чином, метод
буде реалізовано за допомогою коду, схожого на такий:
return [em].createQuery("select c from Customer c where c.lastName=:value").setParameter("value",lastName).getResultList()
де [em] позначає контекст збереження JPA. Це можливо лише за умови, що клас [Customer] має поле з іменем [lastName], що й є у даному випадку.
Отже, у простих випадках Spring Data дозволяє нам реалізувати рівень [DAO] за допомогою простого інтерфейсу.
5.1.4. Рівень [console]
![]() |
![]() |
Клас [Application] має такий вигляд:
package hello;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class Application implements CommandLineRunner {
@Autowired
CustomerRepository repository;
public static void main(String[] args) {
SpringApplication.run(Application.class);
}
@Override
public void run(String... strings) throws Exception {
// зберегти кількох клієнтів
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
// завантажити всіх клієнтів
System.out.println("Customers found with findAll():");
System.out.println("-------------------------------");
for (Customer customer : repository.findAll()) {
System.out.println(customer);
}
System.out.println();
// отримати окремого клієнта за ID
Customer customer = repository.findOne(1L);
System.out.println("Customer found with findOne(1L):");
System.out.println("--------------------------------");
System.out.println(customer);
System.out.println();
// отримати клієнтів за прізвищем
System.out.println("Customer found with findByLastName('Bauer'):");
System.out.println("--------------------------------------------");
for (Customer bauer : repository.findByLastName("Bauer")) {
System.out.println(bauer);
}
}
}
- рядок 9: клас реалізує інтерфейс [CommandLineRunner], який є інтерфейсом [Spring Boot] (рядок 4). Цей інтерфейс має лише один метод, зазначений у рядку 19;
- рядок 8: @SpringBootApplication — це анотація, що об’єднує кілька анотацій [Spring Boot]:
- @Configuration: вказує, що клас є класом конфігурації;
- @EnableAutoConfiguration: вимагає від [Spring Boot] самостійно створити певну кількість бінів залежно від різних властивостей, зокрема від вмісту Classpath проекту. Оскільки бібліотеки Hibernate знаходяться у Classpath, bean [entityManagerFactory] буде реалізовано з використанням Hibernate. Оскільки бібліотека SGBD H2 знаходиться в Classpath, бін [dataSource] буде реалізовано з використанням H2. У біні [dataSource] також потрібно вказати ім’я користувача та його пароль. У цьому випадку Spring Boot використовуватиме адміністратора за замовчуванням з H2, який не має пароля. Оскільки бібліотека [spring-tx] знаходиться у Classpath, буде використовуватися менеджер транзакцій Spring;
- @EnableWebMvc: якщо у Classpath знаходиться бібліотека [spring-mvc]. У цьому випадку для веб-додатка виконується автоконфігурація;
- @ComponentScan: вказує Spring, де шукати інші біни, конфігурації та сервіси. Тут їх за замовчуванням шукають у пакеті, що містить позначений клас, тобто в пакеті [hello]. Таким чином, будуть знайдені класи [Customer] та [CustomerRepository]. Оскільки перший має анотацію [@Entity], він буде каталогізований як об’єкт, що має управлятися Hibernate. Оскільки другий розширює інтерфейс [CrudRepository], він буде зареєстрований як бін Spring;
- рядки 11–12: bean [CustomerRepository] вводиться в код головного класу;
- рядок 15: виконується статичний метод [run] класу [SpringApplication] проекту Spring Boot. Його параметром є клас, що має анотацію [Configuration] або [EnableAutoConfiguration]. Після цього відбудеться все, що було описано раніше. Результатом є контекст додатка Spring, тобто набір бінів, що керуються Spring;
- рядки 19–48: наступні операції лише використовують методи біна, що реалізує інтерфейс [CustomerRepository];
Результати у консолі такі:
- рядки 1–8: логотип проєкту Spring Boot;
- рядок 9: виконується клас [hello.Application];
- рядок 10: [AnnotationConfigApplicationContext] — це клас, що реалізує інтерфейс [ApplicationContext] з Spring. Це контейнер бінів;
- рядок 11: бін [entityManagerFactory] реалізовано за допомогою класу [LocalContainerEntityManagerFactory], класу Spring. Він керує шаром [JPA];
- рядок 12: з’являється [Hibernate]. Саме ця реалізація JPA була обрана;
- рядок 19: діалектом Hibernate є варіант SQL, який слід використовувати разом із SGBD. Тут діалект [H2Dialect] вказує, що Hibernate працюватиме з SGBD та H2;
- рядки 21–22: база даних створена. Створено таблицю [CUSTOMER]. Це означає, що Hibernate було налаштовано на генерацію таблиць на основі визначень JPA, у даному випадку — визначення JPA класу [Customer];
- рядки 26–30: результат виклику методу [findAll] інтерфейсу;
- рядок 34: результат методу [findOne] інтерфейсу;
- рядки 38–39: результати методу [findByLastName];
- рядки 41 і наступні: журнали закриття контексту Spring.
5.1.5. Ручна конфігурація проєкту Spring Data
Ми дублюємо попередній проєкт у проєкті [gs-accessing-data-jpa-02]:
![]() |
У цьому новому проєкті ми не будемо покладатися на автоматичну конфігурацію, виконану Spring Boot. Ми зробимо це вручну. Це може бути корисно, якщо стандартні налаштування нас не влаштовують.
Спочатку ми вкажемо необхідні залежності у файлі [pom.xml]:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework</groupId>
<artifactId>gs-accessing-data-jpa-02</artifactId>
<version>0.1.0</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
</parent>
<dependencies>
<!-- Spring Data -->
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-jpa</artifactId>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
</dependency>
<!-- База даних H2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- Tomcat JDBC -->
<dependency>
<groupId>org.apache.tomcat</groupId>
<artifactId>tomcat-jdbc</artifactId>
</dependency>
</dependencies>
<properties>
<!-- використовуйте UTF-8 для всього -->
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
<repositories>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</repository>
<repository>
<id>org.jboss.repository.releases</id>
<name>JBoss Maven Release Repository</name>
<url>https://repository.jboss.org/nexus/content/repositories/releases</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/libs-release</url>
</pluginRepository>
</pluginRepositories>
</project>
- рядки 10–14: батьківський проект Maven, бібліотеки якого ми будемо використовувати;
- рядки 18–21: Spring Data, що використовується для доступу до бази даних;
- рядки 23–26: реалізація Hibernate специфікації JPA;
- рядки 28–31: SGBD та H2;
- рядки 33–36: бази даних часто використовуються з пулами відкритих з’єднань, що дозволяє уникнути багаторазового відкриття та закриття з’єднань. Тут використовується реалізація [tomcat-jdbc];
У новому проєкті суть [Customer] та інтерфейс [CustomerRepository] залишаються без змін. Ми змінимо клас [Application], який буде розділено на два класи:
- [Config], який буде класом конфігурації:
- [Main], який стане класом виконання;
![]() |
Виконувальний клас [Application] тепер має такий вигляд:
package console;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import repositories.CustomerRepository;
import config.AppConfig;
import entities.Customer;
public class Application {
public static void main(String[] args) {
// інстанціювання контексту Spring
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(AppConfig.class);
CustomerRepository repository = context.getBean(CustomerRepository.class);
// збереження даних кількох клієнтів
repository.save(new Customer("Jack", "Bauer"));
repository.save(new Customer("Chloe", "O'Brian"));
repository.save(new Customer("Kim", "Bauer"));
repository.save(new Customer("David", "Palmer"));
repository.save(new Customer("Michelle", "Dessler"));
...
// закриття контексту
context.close();
}
}
- рядок 9: клас [Application] більше не має анотацій конфігурації;
- рядки 3–7: зверніть увагу, що імпорт пакетів [Spring Boot] більше відсутній;
- рядок 12: створюються екземпляри бінів Spring. Отримується контекст Spring, що містить посилання на створені біни;
- рядок 13: запитується посилання на бін типу [CustomerRepository];
Клас [Config] , який налаштовує проєкт, має такий вигляд:
package config;
import javax.persistence.EntityManagerFactory;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.JpaVendorAdapter;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.orm.jpa.vendor.Database;
import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
@EnableTransactionManagement
@EnableJpaRepositories(basePackages = { "repositories" })
@Configuration
// @ComponentScan(basePackages={"package1","package2"})
public class AppConfig {
// база даних H2
@Bean
public DataSource dataSource() {
// джерело даних TomcatJdbc
DataSource dataSource = new DataSource();
// конфігурація доступу JDBC
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:./demo");
dataSource.setUsername("sa");
dataSource.setPassword("");
// спочатку відкрите з'єднання
dataSource.setInitialSize(1);
// результат
return dataSource;
}
// провайдер JPA
@Bean
public JpaVendorAdapter jpaVendorAdapter() {
HibernateJpaVendorAdapter hibernateJpaVendorAdapter = new HibernateJpaVendorAdapter();
hibernateJpaVendorAdapter.setShowSql(false);
hibernateJpaVendorAdapter.setGenerateDdl(true);
hibernateJpaVendorAdapter.setDatabase(Database.H2);
return hibernateJpaVendorAdapter;
}
// EntityManagerFactory
@Bean
public EntityManagerFactory entityManagerFactory(JpaVendorAdapter jpaVendorAdapter, DataSource dataSource) {
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
factory.setJpaVendorAdapter(jpaVendorAdapter);
factory.setPackagesToScan("entities");
factory.setDataSource(dataSource);
factory.afterPropertiesSet();
return factory.getObject();
}
// Менеджер транзакцій
@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
JpaTransactionManager txManager = new JpaTransactionManager();
txManager.setEntityManagerFactory(entityManagerFactory);
return txManager;
}
}
- рядок 17: анотація [@EnableTransactionManagement] вказує, що анотації [@Transactional] мають бути інтерпретовані. Методи інтерфейсів [CrudRepository] мають ці анотації. Отже, вони виконуються в межах транзакції;
- рядок 18: анотація [@EnableJpaRepositories] дозволяє вказати папки, в яких знаходяться інтерфейси Spring Data [CrudRepository]. Ці інтерфейси стануть компонентами Spring і будуть доступні в його контексті;
- рядок 19: анотація [@Configuration] перетворює клас [Config] на клас конфігурації Spring;
- рядок 20: анотація [@ComponentScan] дозволяє вказати папки, в яких слід шукати компоненти Spring. Компоненти Spring — це класи, позначені анотаціями Spring, такими як @Service, @Component, @Controller тощо. Тут немає інших компонентів, крім тих, що визначені в класі [AppConfig], тому анотація була виведена в коментарі;
- рядки 24–37: визначають джерело даних — базу даних H2. Саме анотація @Bean у рядку 25 робить об’єкт, створений цим методом, компонентом, що керується Spring. Назва методу тут може бути будь-якою. Однак він повинен називатися [dataSource], якщо метод EntityManagerFactory у рядку 51 відсутній і визначається шляхом автоконфігурації;
- рядок 30: база даних матиме назву [demo] і буде згенерована в папці проєкту;
- рядки 40–47: визначають використовувану реалізацію JPA, у даному випадку реалізацію Hibernate. Назва методу тут може бути будь-якою;
- рядок 43: відсутність журналів SQL;
- рядок 44: база даних буде створена, якщо її ще немає;
- рядки 50–58: визначають EntityManagerFactory, який буде керувати збереженням даних JPA. Метод обов’язково має називатися [entityManagerFactory];
- рядок 51: метод отримує два параметри, що мають типи двох раніше визначених бінів. Вони будуть створені, а потім введені Spring як параметри методу;
- рядок 53: визначає реалізацію JPA, що використовується;
- рядок 54: вказує папки, де знаходяться сутності JPA;
- рядок 55: визначає джерело даних, що підлягають обробці;
- рядки 61–66: менеджер транзакцій. Метод обов’язково має називатися [transactionManager]. Він отримує як параметр бін із рядків 51–58;
- рядок 64: менеджер транзакцій пов’язаний з EntityManagerFactory;
Вищезазначені методи можна визначати в будь-якому порядку.
Виконання проєкту дає ті самі результати. У папці проєкту з’являється новий файл — файл бази даних H2:
![]() |
5.1.6. Створення виконуваного архіву
Щоб створити виконуваний архів проекту, можна виконати такі дії:
![]() |
- у [1]: створюється конфігурація виконання;
- у [2]: типу [Java Application]
- у [3]: вказується проект, який потрібно виконати (використовуйте кнопку Browse);
- у [4]: вказує клас, який потрібно виконати;
- у [5]: назва конфігурації виконання — може бути будь-якою;
![]() |
- у [6]: проект експортується;
- у [7]: у вигляді виконуваного архіву JAR;
- в [8]: вказує шлях та ім'я виконуваного файлу, що створюється;
- у [9]: ім’я конфігурації виконання, створеної у [5];
10 ![]() |
- у [10] — створений архів;
Після цього відкриваємо консоль у папці, що містить виконуваний архів:
Архів запускається наступним чином:
.....\dist>java -jar gs-accessing-data-jpa-02.jar
У консолі з’являються такі результати:
5.1.7. Створення проєкту [Spring Data]
Щоб створити шаблон проекту Spring Data, можна виконати такі дії:
![]() |
- у [1] створюється новий проєкт;
- у [2]: типу [Spring Starter Project];
- згенерований проєкт буде проєктом Maven. У [3] вказуємо назву групи проєкту;
- у [4]: вказуємо назву артефакту (у даному випадку — jar-файл), який буде створено під час компіляції проєкту;
- у полі [5]: вказується ім’я проекту в Eclipse — воно може бути будь-яким (не обов’язково збігатися з [4]);
- у [7]: вказується, що буде створено проект, який матиме рівень [JPA] із SGBD та MySQL. Необхідні для такого проєкту залежності будуть включені до файлу [pom.xml];
![]() |
- у [8] вкажіть назву папки проекту;
- у [9] завершіть роботу майстра;
![]() |
- у [10]: створений проект;
Файл [pom.xml] містить необхідні залежності для проекту JPA:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>istia.st.springdata</groupId>
<artifactId>intro-spring-data-01</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>intro-spring-data-01</name>
<description>démo spring data avec table de produits</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.2.3.RELEASE</version>
<relativePath/> <!-- пошук батьківського елемента в репозиторії -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<start-class>demo.IntroSpringData01Application</start-class>
<java.version>1.7</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- рядки 14–19: батьківський проект Maven;
- рядки 28–31: залежність, необхідна для JPA — буде включати [Spring Data];
- рядки 32–36: залежність MySQL від драйвера JDBC;
- рядки 37–41: необхідні залежності для тестів JUnit, інтегрованих із Spring;
Виконуваний клас [Application] нічого не робить, але попередньо налаштований:
package demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class IntroSpringData01Application {
public static void main(String[] args) {
SpringApplication.run(IntroSpringData01Application.class, args);
}
}
- анотація [@SpringBootApplication] робить цей клас класом автоконфігурації проєкту;
Тестовий клас [ApplicationTests] нічого не робить, але попередньо налаштований:
package demo;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = IntroSpringData01Application.class)
public class IntroSpringData01ApplicationTests {
@Test
public void contextLoads() {
}
}
- рядок 9: анотація [@SpringApplicationConfiguration] дозволяє використовувати файл конфігурації [IntroSpringData01Application]. Таким чином, тестовий клас отримає доступ до всіх бінів, визначених у цьому файлі;
- рядок 8: анотація [@RunWith] дозволяє інтегрувати Spring із JUnit: клас можна буде виконати як тест JUnit. [@RunWith] є анотацією JUnit (рядок 4), тоді як клас [SpringJUnit4ClassRunner] є класом Spring (рядок 6);
Тепер, коли ми маємо каркас додатка JPA, можемо його доповнити.




















