Lentegegevens JPA

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:

  1. Creëren en ondersteunen van repositories gemaakt met Spring en JPA
  2. Ondersteuning voor QueryDSL en JPA-query’s
  3. Audit van domeinklassen
  4. Ondersteuning voor batch-laden, sorteren, dynamische query’s
  5. Ondersteunt XML-mapping voor entiteiten
  6. 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.

  1. postgresql: Postgresql Java-driver.
  2. spring-core, spring-context: Kernafhankelijkheden van het Spring Framework.Spring Framework Core-afhankelijkheden.
  3. spring-webmvc, jackson-databind: Voor Spring REST-toepassing.
  4. 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 de LocalContainerEntityManagerFactoryBean-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