Поиск по сайту:

Спринг-данные JPA


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

Спринг-данные JPA

Некоторые из интересных функций, предоставляемых Spring Data JPA:

  1. Создание и поддержка репозиториев, созданных с помощью Spring и JPA
  2. Поддержка запросов QueryDSL и JPA
  3. Аудит классов доменов
  4. Поддержка пакетной загрузки, сортировки, динамических запросов
  5. Поддерживает сопоставление XML для сущностей.
  6. Уменьшите размер кода для общих операций CRUD с помощью CrudRepository

Когда использовать Spring Data JPA?

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

Пример Spring Data JPA

Для нашего примера Spring Data JPA мы создадим веб-службу RESTful, которая будет подключаться к базе данных Postgresql. Мы будем реализовывать основные операции CRUD и работать с уже созданными образцами данных.

Пример данных примера Spring JAP

Используйте приведенный ниже запрос, чтобы создать таблицу в базе данных Postgresql и добавить некоторые тестовые данные.

create table people (
id serial not null primary key,
first_name varchar(20) not null,
last_name varchar(20) not null,
age integer not null
);

insert into people (id, first_name, last_name, age) values
(1, 'Vlad', 'Boyarskiy', 21),
(2,'Oksi', ' Bahatskaya', 30),
(3,'Vadim', ' Vadimich', 32);

Структура проекта Spring Data JPA Maven

Зависимости Spring Data JPA Maven

Нам нужно добавить следующие зависимости для нашего примера проекта Spring Data JPA.

  1. postgresql: Java-драйвер Postgresql.
  2. spring-core, spring-context: зависимости Spring Framework Core.
  3. spring-webmvc, jackson-databind: для приложения Spring REST.
  4. spring-data-jpa, hibernate-entitymanager: для поддержки Spring Data JPA и Hibernate.

Ниже приведено содержимое окончательного файла сборки pom.xml.

<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.journaldev</groupId>
	<artifactId>springData</artifactId>
	<packaging>war</packaging>
	<version>1.0-SNAPSHOT</version>
	<name>Spring Data JPA Maven Webapp</name>
	<url>https://maven.apache.org</url>
	<properties>
		<spring.framework>4.3.0.RELEASE</spring.framework>
		<postgres.version>42.1.4</postgres.version>
		<serializer.version>2.8.1</serializer.version>
		<spring.data>1.3.4.RELEASE</spring.data>
		<hibernate.manager>4.2.5.Final</hibernate.manager>
	</properties>
	<dependencies>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.framework}</version>
		</dependency>
		<dependency>
			<groupId>org.postgresql</groupId>
			<artifactId>postgresql</artifactId>
			<version>${postgres.version}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.framework}</version>
		</dependency>
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-context</artifactId>
			<version>${spring.framework}</version>
		</dependency>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>3.8.1</version>
			<scope>test</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>${spring.data}</version>
		</dependency>

		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-entitymanager</artifactId>
			<version>${hibernate.manager}</version>
		</dependency>
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>${serializer.version}</version>
		</dependency>
	</dependencies>

	<build>
		<finalName>${project.artifactId}</finalName>
	</build>
</project>

Классы конфигурации Spring

package com.journaldev.spring.config;

import java.util.Properties;

import javax.sql.DataSource;

import org.hibernate.ejb.HibernatePersistence;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.env.Environment;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;
import org.springframework.jdbc.datasource.DriverManagerDataSource;
import org.springframework.orm.jpa.JpaTransactionManager;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.transaction.annotation.EnableTransactionManagement;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories("com.journaldev.spring.repository")
@PropertySource("classpath:database.properties")
public class DataConfig {

	private final String PROPERTY_DRIVER = "driver";
	private final String PROPERTY_URL = "url";
	private final String PROPERTY_USERNAME = "user";
	private final String PROPERTY_PASSWORD = "password";
	private final String PROPERTY_SHOW_SQL = "hibernate.show_sql";
	private final String PROPERTY_DIALECT = "hibernate.dialect";

	@Autowired
	Environment environment;

	@Bean
	LocalContainerEntityManagerFactoryBean entityManagerFactory() {
		LocalContainerEntityManagerFactoryBean lfb = new LocalContainerEntityManagerFactoryBean();
		lfb.setDataSource(dataSource());
		lfb.setPersistenceProviderClass(HibernatePersistence.class);
		lfb.setPackagesToScan("com.journaldev.spring.model");
		lfb.setJpaProperties(hibernateProps());
		return lfb;
	}

	@Bean
	DataSource dataSource() {
		DriverManagerDataSource ds = new DriverManagerDataSource();
		ds.setUrl(environment.getProperty(PROPERTY_URL));
		ds.setUsername(environment.getProperty(PROPERTY_USERNAME));
		ds.setPassword(environment.getProperty(PROPERTY_PASSWORD));
		ds.setDriverClassName(environment.getProperty(PROPERTY_DRIVER));
		return ds;
	}

	Properties hibernateProps() {
		Properties properties = new Properties();
		properties.setProperty(PROPERTY_DIALECT, environment.getProperty(PROPERTY_DIALECT));
		properties.setProperty(PROPERTY_SHOW_SQL, environment.getProperty(PROPERTY_SHOW_SQL));
		return properties;
	}

	@Bean
	JpaTransactionManager transactionManager() {
		JpaTransactionManager transactionManager = new JpaTransactionManager();
		transactionManager.setEntityManagerFactory(entityManagerFactory().getObject());
		return transactionManager;
	}
}
  • @Configuration: this spring annotation says that it is configuration class.

  • @EnableTransactionManagement: this annotation allows users to use transaction management in application.

  • @EnableJpaRepositories("com.journaldev.spring.repository"): indicates where the repositories classes are present.

  • @PropertySource("classpath:database.properties"): says that we have property file in our classpath. The values from this file will be injected into environment variable. The contents of the database.properties file are shown below.

    driver=org.postgresql.Driver
    url=jdbc:postgresql://127.0.0.1:5432/postgres
    user=postgres
    password=postgres
    
    hibernate.dialect=org.hibernate.dialect.PostgreSQL82Dialect
    hibernate.show_sql=true
    
  • For using Spring Data, first of all we have to configure DataSource bean. Then we need to configure LocalContainerEntityManagerFactoryBean bean. We need this bean to control the entities. In this beans, you must specify the persistence provider i.e. HibernatePersistence in our case.

  • The next step is to configure bean for annotation.

Классы AppInitializer и WebConfig предназначены для настройки нашего приложения как веб-приложения без использования файла web.xml.

Класс модели

package com.journaldev.spring.model;

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 = "people")
public class Person {

	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Long id;

	@Column(name = "age")
	private Integer age;
	@Column(name = "first_name")
	private String firstName;
	@Column(name = "last_name")
	private String lastName;

	public Person() {
	}

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Integer getAge() {
		return age;
	}

	public void setAge(Integer age) {
		this.age = age;
	}

	public String getFirstName() {
		return firstName;
	}

	public void setFirstName(String firstName) {
		this.firstName = firstName;
	}

	public String getLastName() {
		return lastName;
	}

	public void setLastName(String lastName) {
		this.lastName = lastName;
	}

	@Override
	public String toString() {
		return "Person{" + "id=" + id + ", age=" + age + ", firstName='" + firstName + '\'' + ", lastName='" + lastName
				+ '\'' + '}';
	}
}

Здесь у нас есть несколько новых аннотаций. Поговорим о них подробнее.

  • @Entity: эта аннотация позволяет менеджеру сущностей использовать этот класс и помещает его в контекст.
  • @Table(name=\people): связывает класс с таблицей в базе данных.
  • @Id: говорит, что это поле является первичным ключом.
  • @GeneratedValue(strategy=GenerationType.IDENTITY): определяет стратегию создания первичного ключа.
  • @Column(name=age): обозначает столбец в базе данных, с которым будет связано это поле.

Репозиторий данных Spring JPA

Следующим шагом является создание репозитория JPA.

package com.journaldev.spring.repository;

import org.springframework.data.repository.CrudRepository;

import com.journaldev.spring.model.Person;

import java.util.List;

public interface PersonRepository<P> extends CrudRepository<Person, Long> {
    List<Person> findByFirstName(String firstName);
}

Наследуя от CrudRepository, мы можем вызывать множество методов без необходимости их реализации самостоятельно. Вот некоторые из этих методов:

  • сохранить
  • найти
  • существует
  • найти все
  • количество
  • удалить
  • удалить все

Мы также можем определить наши собственные методы. Эти имена методов должны использовать специальные ключевые слова, такие как «найти», «заказать» с именем переменных. Разработчики Spring Data JPA постарались учесть большинство возможных опций, которые могут вам понадобиться. В нашем примере метод findByFirstName(String firstName) возвращает все записи из таблицы, где поле first_name равно firstName. Это одна из наиболее важных функций Spring Data JPA, поскольку она сокращает объем стандартного кода. Также вероятность ошибок меньше, потому что эти методы Spring хорошо протестированы во многих проектах, которые уже используют их.

Весенний класс обслуживания

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

package com.journaldev.spring.services;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.journaldev.spring.model.Person;
import com.journaldev.spring.repository.PersonRepository;

@Service
public class PersonService {

	@Autowired
	PersonRepository<Person> personRepository;

	@Transactional
	public List<Person> getAllPersons() {
		return (List<Person>) personRepository.findAll();
	}

	@Transactional
	public List<Person> findByName(String name) {
		return personRepository.findByFirstName(name);
	}

	@Transactional
	public Person getById(Long id) {
		return personRepository.findOne(id);
	}

	@Transactional
	public void deletePerson(Long personId) {
		personRepository.delete(personId);
	}

	@Transactional
	public boolean addPerson(Person person) {
		return personRepository.save(person) != null;
	}

	@Transactional
	public boolean updatePerson(Person person) {
		return personRepository.save(person) != null;
	}
}

Аннотация @Transactional указывает, что метод будет выполняться в транзакции. Spring позаботится об управлении транзакциями.

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

Последним шагом является создание класса контроллера, чтобы представить наши API-интерфейсы внешнему миру.

package com.journaldev.spring.controller;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.PathVariable;
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.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.journaldev.spring.model.Person;
import com.journaldev.spring.services.PersonService;

@RestController
public class PersonController {

	@Autowired
	PersonService personService;

	@RequestMapping(value = "/person/{id}", method = RequestMethod.GET)
	public @ResponseBody Person getAllUsers(@PathVariable Long id) {
		return personService.getById(id);
	}

	@RequestMapping(value = "/personByName/{name}", method = RequestMethod.GET)
	public List<Person> getPersoneByName(@PathVariable String name) {
		return personService.findByName(name);
	}

	@RequestMapping(value = "/person", method = RequestMethod.GET)
	public List<Person> getAll() {
		return personService.getAllPersons();
	}

	@RequestMapping(value = "/person/{id}", method = RequestMethod.DELETE)
	public HttpStatus deletePersnone(@PathVariable Long id) {
		personService.deletePerson(id);
		return HttpStatus.NO_CONTENT;
	}

	@RequestMapping(value = "/person", method = RequestMethod.POST)
	public HttpStatus insertPersone(@RequestBody Person person) {
		return personService.addPerson(person) ? HttpStatus.CREATED : HttpStatus.BAD_REQUEST;
	}

	@RequestMapping(value = "/person", method = RequestMethod.PUT)
	public HttpStatus updatePerson(@RequestBody Person person) {
		return personService.updatePerson(person) ? HttpStatus.ACCEPTED : HttpStatus.BAD_REQUEST;
	}
}

JPA-тестирование Spring Data

Просто создайте и разверните проект в своем любимом контейнере сервлетов, таком как Tomcat. На изображениях ниже показаны ответы на некоторые вызовы API.

Spring Data JPA Читать все
Spring Данные JPA Получить по имени
Spring Данные JPA Создать
Обновление Spring данных JPA
Spring Данные JPA Удалить

Скачать пример проекта Spring Data JPA

Ссылка: Официальный сайт