# 使用 JPA 配置的 Spring REST CRUD 示例

> 原文： [https://howtodoinjava.com/spring-restful/spring-rest-crud-jpa-example/](https://howtodoinjava.com/spring-restful/spring-rest-crud-jpa-example/)

学习**使用 **Spring REST 和 JPA** 配置（以 H2 数据库为后端）**创建 [REST API](https://restfulapi.net) 以进行分类操作**，而无需 [Spring boot](https://howtodoinjava.com/spring-boot-tutorials/)** 自动配置功能。

## 1\. Maven 依赖

在此示例中，我们使用以下模块及其依赖项。

*   `spring-webmvc` – 用于处理请求
*   `spring-data-jpa` – 为接口提供了支持针对后端数据存储读取，更新，删除和创建记录的方法。
*   `persistence-api` – JPA 规范
*   `javax.persistence` -JPA 实现
*   **Hibernate 实体管理器** – 作为实体供体商
*   **Jackson** – 用于 JSON 支持
*   **H2** – 作为数据库

`pom.xml`

```java
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.howtodoinjava.rest</groupId>
	<artifactId>SpringRestExample</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>war</packaging>

	<name>SpringRestExample</name>
	<url>http://maven.apache.org</url>

	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<spring.version>5.1.6.RELEASE</spring.version>
		<maven.compiler.source>1.8</maven.compiler.source>
    	<maven.compiler.target>1.8</maven.compiler.target>
	</properties>

	<dependencies>
		<!-- spring webmvc -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- spring data jpa -->
		<dependency>
			<groupId>org.springframework.data</groupId>
			<artifactId>spring-data-jpa</artifactId>
			<version>2.1.6.RELEASE</version>
		</dependency>

		<!-- persistence api -->
		<dependency>
			<groupId>javax.persistence</groupId>
			<artifactId>persistence-api</artifactId>
			<version>1.0.2</version>
		</dependency>

		<!-- persistence implementation -->
		<dependency>
			<groupId>org.eclipse.persistence</groupId>
			<artifactId>javax.persistence</artifactId>
			<version>2.1.0</version>
		</dependency>

		<!-- entity manager provider -->
		<dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>5.4.2.Final</version>
        </dependency>

        <!-- H2 database -->
		<dependency>
			<groupId>com.h2database</groupId>
			<artifactId>h2</artifactId>
			<version>1.4.199</version> 
		</dependency>

		<!-- JSON support -->
		<dependency>
			<groupId>com.fasterxml.jackson.core</groupId>
			<artifactId>jackson-databind</artifactId>
			<version>2.9.8</version>
		</dependency>
	</dependencies>
</project>

```

## 2\. `DispatcherServlet`声明

我们已经在`web.xml`文件中配置了[`DispatcherServlet`](https://howtodoinjava.com/spring5/webmvc/spring-dispatcherservlet-tutorial/)，该文件会将传入的请求路由到适当的控制器方法。

`web.xml`

```java
<!DOCTYPE web-app PUBLIC
 "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
 "http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
	<display-name>Employee Management REST APIs</display-name>

	<servlet>
		<servlet-name>rest</servlet-name> 
		<servlet-class>
			org.springframework.web.servlet.DispatcherServlet
		</servlet-class>
		<load-on-startup>1</load-on-startup>
	</servlet>

	<servlet-mapping>
		<servlet-name>rest</servlet-name>
		<url-pattern>/api/rest/*</url-pattern>
	</servlet-mapping>

</web-app>

```

## 3\. Spring 和 JPA 配置

在`rest-servlet.xml`文件中，我们已经配置了[组件扫描和基于注解的配置](https://howtodoinjava.com/spring5/core/spring-bean-container-java-configuration-example/)支持。 随之，我们配置了实体管理器和数据源配置。

`rest-servlet.xml`

```java
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:jpa="http://www.springframework.org/schema/data/jpa"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
	http://www.springframework.org/schema/beans/spring-beans.xsd
	http://www.springframework.org/schema/context
	http://www.springframework.org/schema/context/spring-context.xsd
	http://www.springframework.org/schema/data/jpa 
    http://www.springframework.org/schema/data/jpa/spring-jpa-1.0.xsd
    http://www.springframework.org/schema/tx 
    http://www.springframework.org/schema/tx/spring-tx-4.0.xsd
	http://www.springframework.org/schema/mvc
	http://www.springframework.org/schema/mvc/spring-mvc.xsd">

	<context:component-scan base-package="com.howtodoinjava.demo" />
	<mvc:annotation-driven />
	<jpa:repositories base-package="com.howtodoinjava.demo.repository" entity-manager-factory-ref="emf"/>

	<bean id="emf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
	    <property name="packagesToScan" value="com.howtodoinjava.demo.model" />
	    <property name="dataSource" ref="dataSource" />

	    <property name="jpaProperties">
	        <props>
	            <prop key="hibernate.show_sql">true</prop>
	            <prop key="hibernate.format_sql">true</prop>
	            <prop key="hibernate.hbm2ddl.auto">create</prop>
	            <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
	        </props>
	    </property>

	    <property name="persistenceProvider">
	        <bean class="org.hibernate.jpa.HibernatePersistenceProvider"></bean>
	    </property>

	</bean>

	<bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource" id="dataSource">
        <property name="driverClass" value="org.h2.Driver" />
        <property name="url" value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;TRACE_LEVEL_SYSTEM_OUT=2" />
    </bean>

	<tx:annotation-driven transaction-manager="transactionManager" />

	<bean class="org.springframework.orm.jpa.JpaTransactionManager"  id="transactionManager">
	    <property name="dataSource" ref="dataSource" />
	</bean>
</beans>

```

## 4\. 实体类

我们只有一个实体类，它将保留在数据库中，并将作为 REST API 的响应返回。

*   `@Entity` – JPA 注解，以使对象准备好存储在基于 JPA 的数据存储区中。
*   `@Table` – 数据存储中将存储此实体的表的名称。

> 阅读更多： [JPA 2 持久性注解](https://howtodoinjava.com/hibernate/hibernate-jpa-2-persistence-annotations-tutorial/)

`Employee.java`

```java
import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "tbl_employee")
public class Employee implements Serializable {
	private static final long serialVersionUID = 1L;

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

	private String firstName;

	private String lastName;

	private String email;

	public Employee() {
	}

	//Getters and setters

	@Override
	public String toString() {
		return "EmployeeVO [id=" + id + ", firstName=" + firstName + ", 
				lastName=" + lastName + ", email=" + email	+ "]";
	}
}

```

## 5\. 存储库

我们已将`JpaRepository`实现创建为`EmployeeRepository`，它提供了用于对员工实体执行搜索，获取，更新和删除操作的所有默认操作。

`EmployeeRepository.java`

```java
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.howtodoinjava.demo.model.Employee;

@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {

}

```

## 6\. REST 控制器

REST 控制器定义了可以调用以对员工资源执行操作的所有 CRUD 方法。

在给定的控制器中，`@RestController`注解指示方法返回的数据将直接写入响应主体中，而不呈现模板。 其他注解（`@GetMapping`，`@PostMapping`，`@PutMapping`和`@DeleteMapping`）将 HTTP 请求映射到相应的方法。

`EmployeeRESTController.java`

```java
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.howtodoinjava.demo.model.Employee;
import com.howtodoinjava.demo.repository.EmployeeRepository;

@RestController
@RequestMapping(value = "/employee-management", produces = { MediaType.APPLICATION_JSON_VALUE })
public class EmployeeRESTController 
{
	@Autowired
	private EmployeeRepository repository;

	public EmployeeRepository getRepository() {
		return repository;
	}

	public void setRepository(EmployeeRepository repository) {
		this.repository = repository;
	}

	@GetMapping(value = "/employees")
	public List<Employee> getAllEmployees() {
		return repository.findAll();
	}

	@PostMapping("/employees")
	Employee createOrSaveEmployee(@RequestBody Employee newEmployee) {
		return repository.save(newEmployee);
	}

	@GetMapping("/employees/{id}")
	Employee getEmployeeById(@PathVariable Long id) {
		return repository.findById(id).get();
	}

	@PutMapping("/employees/{id}")
	Employee updateEmployee(@RequestBody Employee newEmployee, @PathVariable Long id) {

		return repository.findById(id).map(employee -> {
			employee.setFirstName(newEmployee.getFirstName());
			employee.setLastName(newEmployee.getLastName());
			employee.setEmail(newEmployee.getEmail());
			return repository.save(employee);
		}).orElseGet(() -> {
			newEmployee.setId(id);
			return repository.save(newEmployee);
		});
	}

	@DeleteMapping("/employees/{id}")
	void deleteEmployee(@PathVariable Long id) {
		repository.deleteById(id);
	}
}

```

## 7\. Spring REST CRUD 操作演示

让我们测试一下 API 操作，以验证它们是否有效。

#### 7.1. 创建员工

`API Request`

```java
HTTP POST : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees

{
    "firstName": "lokesh",
    "lastName": "gupta",
    "email": "abc@gmail.com"
}

```

`API Response`

```java
HTTP Response code : 200

{
	"id": 1,
	"firstName": "lokesh",
	"lastName": "gupta",
	"email": "abc@gmail.com"
}

```

创建更多的员工进行测试。

#### 7.2. 获取员工集合

`API Request`

```java
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees

```

`API Response`

```java
HTTP Response code : 200

[
	{
		"id": 1,
		"firstName": "lokesh",
		"lastName": "gupta",
		"email": "abc@gmail.com"
	},
	{
		"id": 2,
		"firstName": "Amit",
		"lastName": "Sharma",
		"email": "xyz@gmail.com"
	}
]

```

#### 7.3. 按编号获取员工

`API Request`

```java
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1

```

`API Response`

```java
HTTP Response code : 200

{
	"id": 1,
	"firstName": "lokesh",
	"lastName": "gupta",
	"email": "abc@gmail.com"
}

```

#### 7.4. 更新员工

`API Request`

```java
HTTP PUT : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1

{
    "firstName": "Lucky",
    "lastName": "Gupta",
    "email": "abc@gmail.com"
}

```

`API Response`

```java
HTTP Response code : 200

{
	"id": 1,
	"firstName": "Lucky",
	"lastName": "Gupta",
	"email": "abc@gmail.com"
}

```

#### 7.5. 删除员工

`API Request`

```java
HTTP DELETE : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1

```

`API Response`

```java
HTTP Response code : 200

```

学习愉快！

[下载源码](https://howtodoinjava.com/wp-content/downloads/SpringRestExample.zip)