Spring Data JPA

Spring Data JPA fait partie de la famille Spring Data. Spring Data facilite la création d’applications pilotées par Spring qui utilisent de nouvelles façons d’accéder aux données, telles que les bases de données non relationnelles, les frameworks de réduction de cartes, les services cloud, ainsi qu’une prise en charge avancée des bases de données relationnelles. Cet article abordera Spring Data JPA. Nous examinerons également un exemple d’application Spring Data JPA.

Spring Data JPA

Voici quelques-unes des fonctionnalités intéressantes fournies par Spring Data JPA :

  1. Créer et prendre en charge des référentiels créés avec Spring et JPA
  2. Prise en charge de QueryDSL et des requêtes JPA
  3. Audit des classes de domaine
  4. Prise en charge du chargement par lots, du tri et des requêtes dynamiques
  5. Prise en charge de la mise en correspondance XML pour les entités
  6. Réduire la taille du code pour les opérations génériques de CRUD en utilisant CrudRepository

Quand utiliser Spring Data JPA ?

I would say that if you need to quickly create a JPA-based repository layer that is mainly for CRUD operations, and you do not want to create abstract DAO, implementing interfaces, Spring Data JPA is a good choice.

Exemple de Spring Data JPA

Pour notre exemple Spring Data JPA, nous allons créer un service web RESTful qui se connectera à la base de données Postgresql. Nous implémenterons des opérations CRUD de base et travaillerons sur des données d’exemple que nous avons déjà créées.

Données d’exemple de l’exemple Spring JPA

Utilisez la requête ci-dessous pour créer une table dans la base de données Postgresql et ajouter quelques données de test.

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);

Structure du projet Maven Spring Data JPA

L’image ci-dessous montre la structure finale du projet Spring JPA. Nous examinerons ensuite en détail chacun des composants.

Dépendances Maven Spring Data JPA

Nous devons ajouter les dépendances suivantes pour notre projet d’exemple Spring Data JPA.

  1. postgresql: Pilote Java Postgresql.
  2. spring-core, spring-context: Dépendances principales du framework Spring.
  3. spring-webmvc, jackson-databind: Pour une application REST avec Spring.
  4. spring-data-jpa, hibernate-entitymanager: Pour la prise en charge de Spring Data JPA et Hibernate.

Voici le contenu final du fichier de construction 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>

Classes de configuration 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: cette annotation Spring indique qu’il s’agit d’une classe de configuration.

  • @EnableTransactionManagement: cette annotation permet aux utilisateurs d’utiliser la gestion des transactions dans l’application.

  • @EnableJpaRepositories("com.journaldev.spring.repository"): indique où se trouvent les classes de dépôt (repositories).

  • @PropertySource("classpath:database.properties"): indique que nous avons un fichier de propriétés dans notre classpath. Les valeurs de ce fichier seront injectées dans la variable d’environnement. Le contenu du fichier database.properties est indiqué ci-dessous.

    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
    
  • Pour utiliser Spring Data, tout d’abord, nous devons configurer le bean DataSource. Ensuite, nous devons configurer le bean LocalContainerEntityManagerFactoryBean. Nous avons besoin de ce bean pour contrôler les entités. Dans ces beans, vous devez spécifier le fournisseur de persistance, c’est-à-dire HibernatePersistence dans notre cas.

  • La prochaine étape consiste à configurer le bean pour la gestion des transactions. Dans notre exemple, il s’agit de JpaTransactionManager. Notez qu’il est nécessaire de configurer le gestionnaire de transactions pour pouvoir utiliser l’annotation @Transactional .

Les classes AppInitializer et WebConfig servent à configurer notre application en tant qu’application web sans utiliser le fichier web.xml.

Classe de modèle

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
				+ '\'' + '}';
	}
}

Ici, nous avons quelques nouvelles annotations. Parlons-en plus en détail.

  • @Entity: Cette annotation permet au gestionnaire d’entité d’utiliser cette classe et de la mettre en contexte.
  • @Table(name = « people »): Associe une classe à une table dans la base de données.
  • @Id: Indique que ce champ est la clé primaire.
  • @GeneratedValue(strategy = GenerationType.IDENTITY): Définit la stratégie de génération de la clé primaire.
  • @Column(name = "age"): indique une colonne dans la base de données avec laquelle ce champ sera associé.

Spring Data JPA Repository

La prochaine étape consiste à créer le référentiel 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);
}

En héritant de CrudRepository, nous pouvons appeler de nombreuses méthodes sans avoir besoin de les implémenter nous-mêmes. Certaines de ces méthodes sont:

  • save
  • findOne
  • exists
  • findAll
  • count
  • delete
  • deleteAll

Nous pouvons également définir nos propres méthodes. Ces noms de méthode doivent utiliser des mots-clés spéciaux tels que « find », « order » avec le nom des variables. Les développeurs de Spring Data JPA ont essayé de prendre en compte la majorité des options possibles dont vous pourriez avoir besoin. Dans notre exemple, la méthode findByFirstName(String firstName) renvoie toutes les entrées de la table où le champ first_name est égal à firstName. Il s’agit de l’une des fonctionnalités les plus importantes de Spring Data JPA car elle réduit beaucoup de code répétitif. De plus, les chances d’erreurs sont moindres car ces méthodes Spring sont bien testées par de nombreux projets qui les utilisent déjà.

Classe de service Spring

Maintenant que notre code Spring Data JPA est prêt, la prochaine étape consiste à créer une classe de service et à définir les méthodes avec lesquelles nous devrons travailler avec la table de la base de données.

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 annotation indique que la méthode sera exécutée dans la transaction. Spring se chargera de la gestion de la transaction.

Classe de contrôleur Spring

La dernière étape consiste à créer la classe de contrôleur pour exposer nos API au monde extérieur.

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;
	}
}

Tests Spring Data JPA

Il vous suffit de construire et déployer le projet dans votre conteneur de servlet préféré, tel que Tomcat. Les images ci-dessous montrent la réponse pour certaines des appels d’API.

Spring Data JPA Lire tout

Spring Data JPA Obtenir par nom

Spring Data JPA Créer

Spring Data JPA Mettre à jour

Spring Data JPA Supprimer

C’est tout pour le tutoriel exemple de Spring Data JPA. Vous pouvez télécharger le projet final depuis le lien ci-dessous.

Télécharger le projet exemple Spring Data JPA

Référence : Site officiel

Source:
https://www.digitalocean.com/community/tutorials/spring-data-jpa