Spring Data JPA maakt deel uit van de Spring Data-familie. Spring Data maakt het gemakkelijker om Spring-gestuurde applicaties te maken die nieuwe manieren gebruiken om gegevens te benaderen, zoals niet-relationele databases, map-reductie frameworks, cloudservices, evenals geavanceerde ondersteuning voor relationele databases. Dit artikel zal ingaan op Spring Data JPA. We zullen ook kijken naar een voorbeeldtoepassing van Spring Data JPA.
Spring Data JPA
Enkele van de interessante functies die Spring Data JPA biedt, zijn:
- Creëren en ondersteunen van repositories gemaakt met Spring en JPA
- Ondersteuning voor QueryDSL en JPA-query’s
- Audit van domeinklassen
- Ondersteuning voor batch-laden, sorteren, dynamische query’s
- Ondersteunt XML-mapping voor entiteiten
- Verminder de codegrootte voor generieke CRUD-operaties door gebruik te maken van CrudRepository
Wanneer gebruik je 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.
Voorbeeld van Spring Data JPA
Voor ons Spring Data JPA-voorbeeld zullen we een RESTful-webservice maken die verbinding maakt met de Postgresql-database. We zullen basis-CRUD-operaties implementeren en werken met voorbeeldgegevens die we al hebben aangemaakt.
Voorbeeldgegevens Spring JPA
Gebruik onderstaande query om een tabel te maken in de Postgresql-database en voeg enkele testgegevens toe.
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 Projectstructuur
De onderstaande afbeelding toont de uiteindelijke structuur van het Spring JPA-project. We zullen later in detail naar elk van de componenten kijken.
Spring Data JPA Maven-afhankelijkheden
We moeten de volgende afhankelijkheden toevoegen voor ons Spring Data JPA-voorbeeldproject.
postgresql
: Postgresql Java-driver.spring-core
,spring-context
: Kernafhankelijkheden van het Spring Framework.Spring Framework Core-afhankelijkheden.spring-webmvc
,jackson-databind
: Voor Spring REST-toepassing.spring-data-jpa
,hibernate-entitymanager
: voor Spring Data JPA en Hibernate-ondersteuning.
Hieronder staat de inhoud van het uiteindelijke pom.xml-buildbestand.
<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-configuratieklassen
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
: deze Spring-annotatie geeft aan dat het een configuratieklasse is. -
@EnableTransactionManagement
: deze annotatie stelt gebruikers in staat transactiebeheer in de toepassing te gebruiken. -
@EnableJpaRepositories("com.journaldev.spring.repository")
: geeft aan waar de repositoryklassen aanwezig zijn. -
@PropertySource("classpath:database.properties")
: zegt dat we een eigenschappenbestand hebben in onze classpath. De waarden uit dit bestand zullen worden geïnjecteerd in de omgevingsvariabele. De inhoud van het database.properties-bestand wordt hieronder weergegeven.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
-
Om Spring Data te gebruiken, moeten we allereerst de
DataSource
-bean configureren. Vervolgens moeten we deLocalContainerEntityManagerFactoryBean
-bean configureren. We hebben deze bean nodig om de entiteiten te beheren. In deze beans moet je de persistentieprovider specificeren, d.w.z.HibernatePersistence
in ons geval. -
De volgende stap is het configureren van de bean voor transactiebeheer. In ons voorbeeld is het
JpaTransactionManager
. Let op dat zonder het configureren van het transactiebeheer we de@Transactional
annotatie niet kunnen gebruiken.
AppInitializer
en WebConfig
klassen worden gebruikt om onze applicatie te configureren als een webapplicatie zonder het gebruik van het web.xml-bestand.
Modelklasse
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 hebben we een paar nieuwe annotaties. Laten we er wat meer in detail over praten.
- @Entity: Deze annotatie staat de entity manager toe om deze klasse te gebruiken en plaatst deze in de context.
- @Table(name = “people”): koppelt een klasse aan een tabel in de database.
@Id
: Geeft aan dat dit veld de primaire sleutel is.@GeneratedValue(strategy = GenerationType.IDENTITY)
: Definieert de strategie voor het genereren van de primaire sleutel.@Column(name = "age")
: duidt een kolom in de database aan waarmee dit veld zal worden geassocieerd.
Spring Data JPA Repository
De volgende stap is het maken van de JPA-repository.
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);
}
Door over te erven van CrudRepository
, kunnen we veel methoden aanroepen zonder ze zelf te hoeven implementeren. Enkele van deze methoden zijn:
- save
- findOne
- exists
- findAll
- count
- delete
- deleteAll
We kunnen ook onze eigen methoden definiëren. Deze methodenamen moeten speciale trefwoorden gebruiken zoals “find”, “order” met de naam van de variabelen. Spring Data JPA-ontwikkelaars hebben geprobeerd rekening te houden met de meerderheid van mogelijke opties die je nodig zou kunnen hebben. In ons voorbeeld retourneert de methode findByFirstName(String firstName)
alle vermeldingen uit de tabel waar het veld first_name
gelijk is aan firstName
. Dit is een van de belangrijkste functies van Spring Data JPA omdat het veel boilerplate code vermindert. Ook zijn de kansen op fouten kleiner omdat deze Spring-methoden al goed zijn getest door veel projecten die ze al gebruiken.
Spring Service Class
Nu onze Spring Data JPA-code gereed is, is de volgende stap het maken van een serviceklasse en het definiëren van methoden waarmee we moeten werken met de database tabel.
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
annotatie geeft aan dat de methode zal worden uitgevoerd in de transactie. Spring zal voor het transactiebeheer zorgen.
Spring Controller Class
Laatste stap is het maken van de controllerklasse om onze API’s bloot te stellen aan de buitenwereld.
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
Bouw en implementeer gewoon het project in uw favoriete servlet-container zoals Tomcat. Hieronder staan afbeeldingen van de respons op enkele van de API-aanroepen.
Spring Data JPA Alles Lezen
Spring Data JPA Ophalen Op Naam
Spring Data JPA Maken
Spring Data JPA Bijwerken
Spring Data JPA Verwijderen
Dat is alles voor de Spring Data JPA-voorbeeldtutorial. U kunt het eindproject downloaden via onderstaande link.
Download Spring Data JPA Voorbeeldproject
Referentie: Officiële Website
Source:
https://www.digitalocean.com/community/tutorials/spring-data-jpa