Spring Data JPA

Spring Data JPA ist Teil der Spring Data-Familie. Spring Data erleichtert die Erstellung von Spring-getriebenen Anwendungen, die neue Möglichkeiten zum Zugriff auf Daten verwenden, wie z.B. nicht-relationale Datenbanken, Map-Reduktion-Frameworks, Cloud-Services sowie umfangreiche Unterstützung für relationale Datenbanken. Dieser Artikel wird über Spring Data JPA sprechen. Wir werden uns auch eine Beispielanwendung für Spring Data JPA ansehen.

Spring Data JPA

Einige der coolen Funktionen, die Spring Data JPA bietet, sind:

  1. Erstellen und Unterstützen von Repositories, die mit Spring und JPA erstellt wurden
  2. Unterstützung für QueryDSL und JPA-Abfragen
  3. Audit von Domänenklassen
  4. Unterstützung für Stapelladen, Sortieren, dynamische Abfragen
  5. Unterstützt XML-Mapping für Entitäten
  6. Verringerung der Codegröße für generische CRUD-Operationen durch Verwendung von CrudRepository

Wann sollte man Spring Data JPA verwenden?

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.

Beispiel für Spring Data JPA

Für unser Beispiel mit Spring Data JPA werden wir einen RESTful-Webdienst erstellen, der sich mit der PostgreSQL-Datenbank verbindet. Wir werden grundlegende CRUD-Operationen implementieren und mit Beispieldaten arbeiten, die wir bereits erstellt haben.

Beispiel für Spring JPA-Daten

Verwenden Sie die folgende Abfrage, um eine Tabelle in der PostgreSQL-Datenbank zu erstellen und einige Testdaten hinzuzufügen.

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 Projektstruktur

Das folgende Bild zeigt die endgültige Struktur des Spring JPA-Projekts. Wir werden uns später detailliert mit jedem der Komponenten befassen.

Abhängigkeiten für Spring Data JPA in Maven

Für unser Beispielprojekt mit Spring Data JPA müssen wir folgende Abhängigkeiten hinzufügen.

  1. postgresql: PostgreSQL Java-Treiber.
  2. spring-core, spring-context: Kernabhängigkeiten des Spring-Frameworks.
  3. spring-webmvc, jackson-databind: Für die Spring-REST-Anwendung.
  4. spring-data-jpa, hibernate-entitymanager: für Spring Data JPA und die Unterstützung von Hibernate.

Im Folgenden finden Sie den Inhalt der endgültigen pom.xml-Build-Datei.

<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-Konfigurationsklassen

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: Diese Spring-Annotation besagt, dass es sich um eine Konfigurationsklasse handelt.

  • @EnableTransactionManagement: Diese Annotation ermöglicht es den Benutzern, das Transaktionsmanagement in der Anwendung zu verwenden.

  • @EnableJpaRepositories("com.journaldev.spring.repository"): gibt an, wo sich die Repository-Klassen befinden.

  • @PropertySource("classpath:database.properties"): besagt, dass wir eine Eigenschaftsdatei in unserem Klassenpfad haben. Die Werte aus dieser Datei werden in Umgebungsvariablen eingefügt. Der Inhalt der database.properties-Datei wird unten angezeigt.

    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
    
  • Um Spring Data zu verwenden, müssen wir zunächst den DataSource-Bean konfigurieren. Dann müssen wir den LocalContainerEntityManagerFactoryBean-Bean konfigurieren. Wir benötigen diesen Bean, um die Entitäten zu steuern. In diesen Beans müssen Sie den Persistenzanbieter angeben, d.h. HibernatePersistence in unserem Fall.

  • Der nächste Schritt besteht darin, den Bean für das Transaktionsmanagement zu konfigurieren. In unserem Beispiel ist es JpaTransactionManager. Beachten Sie, dass ohne Konfiguration des Transaktionsmanagers das @Transactional Annotation nicht verwendet werden kann.

AppInitializer– und WebConfig-Klassen dienen dazu, unsere Anwendung als Webanwendung zu konfigurieren, ohne die Datei web.xml zu verwenden.

Model-Klasse

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

Hier haben wir einige neue Annotationen. Lassen Sie uns näher darauf eingehen.

  • @Entity: Diese Annotation ermöglicht es dem Entity Manager, diese Klasse zu verwenden und sie im Kontext zu platzieren.
  • @Table(name = „people“): ordnet eine Klasse einer Tabelle in der Datenbank zu.
  • @Id: besagt, dass dieses Feld der Primärschlüssel ist.
  • @GeneratedValue(strategy = GenerationType.IDENTITY): Definiert die Strategie zur Generierung des Primärschlüssels.
  • @Column(name = "age"): gibt eine Spalte in der Datenbank an, mit der dieses Feld verknüpft wird.

Spring Data JPA Repository

Der nächste Schritt besteht darin, das JPA-Repository zu erstellen.

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

Indem wir von CrudRepository erben, können wir viele Methoden aufrufen, ohne sie selbst implementieren zu müssen. Einige dieser Methoden sind:

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

Wir können auch unsere eigenen Methoden definieren. Diese Methodennamen sollten spezielle Schlüsselwörter wie „find“ oder „order“ mit dem Namen der Variablen verwenden. Die Entwickler von Spring Data JPA haben versucht, die meisten möglichen Optionen zu berücksichtigen, die Sie möglicherweise benötigen. In unserem Beispiel gibt die Methode findByFirstName(String firstName) alle Einträge aus der Tabelle zurück, bei denen das Feld first_name dem Wert firstName entspricht. Dies ist eine der wichtigsten Funktionen von Spring Data JPA, da sie eine Menge Boilerplate-Code reduziert. Außerdem sind die Chancen auf Fehler geringer, da diese Spring-Methoden bereits von vielen Projekten getestet wurden, die sie verwenden.

Spring Service Klasse

Jetzt, da unser Spring Data JPA Code bereit ist, ist der nächste Schritt die Erstellung einer Service-Klasse und die Definition von Methoden, mit denen wir mit der Datenbanktabelle arbeiten müssen.

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 zeigt an, dass die Methode in der Transaktion ausgeführt wird. Spring kümmert sich um das Transaktionsmanagement.

Spring Controller Klasse

Der letzte Schritt besteht darin, die Controller-Klasse zu erstellen, um unsere APIs der äußeren Welt zugänglich zu machen.

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

Spring Data JPA Testen

Einfach das Projekt erstellen und in Ihren bevorzugten Servlet-Container wie Tomcat bereitstellen. Die folgenden Bilder zeigen die Antwort auf einige der API-Aufrufe.

Spring Data JPA Alle lesen

Spring Data JPA Nach Namen erhalten

Spring Data JPA Erstellen

Spring Data JPA Aktualisieren

Spring Data JPA Löschen

Das ist alles für das Spring Data JPA Beispiel-Tutorial. Sie können das endgültige Projekt über den folgenden Link herunterladen.

Projektbeispiel für Spring Data JPA herunterladen

Referenz: Offizielle Website

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