原文: https://howtodoinjava.com/spring-restful/spring-rest-crud-jpa-example/
学习使用 Spring REST 和 JPA 配置(以 H2 数据库为后端)创建 REST API 以进行分类操作,而无需 Spring boot 自动配置功能。
1. Maven 依赖
在此示例中,我们使用以下模块及其依赖项。
spring-webmvc
– 用于处理请求spring-data-jpa
– 为接口提供了支持针对后端数据存储读取,更新,删除和创建记录的方法。persistence-api
– JPA 规范javax.persistence
-JPA 实现- Hibernate 实体管理器 – 作为实体供体商
- Jackson – 用于 JSON 支持
- H2 – 作为数据库
pom.xml
<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
,该文件会将传入的请求路由到适当的控制器方法。
web.xml
<!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
文件中,我们已经配置了组件扫描和基于注解的配置支持。 随之,我们配置了实体管理器和数据源配置。
rest-servlet.xml
<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 持久性注解
Employee.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
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
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
HTTP POST : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees
{
"firstName": "lokesh",
"lastName": "gupta",
"email": "abc@gmail.com"
}
API Response
HTTP Response code : 200
{
"id": 1,
"firstName": "lokesh",
"lastName": "gupta",
"email": "abc@gmail.com"
}
创建更多的员工进行测试。
7.2. 获取员工集合
API Request
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees
API Response
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
HTTP GET : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
API Response
HTTP Response code : 200
{
"id": 1,
"firstName": "lokesh",
"lastName": "gupta",
"email": "abc@gmail.com"
}
7.4. 更新员工
API Request
HTTP PUT : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
{
"firstName": "Lucky",
"lastName": "Gupta",
"email": "abc@gmail.com"
}
API Response
HTTP Response code : 200
{
"id": 1,
"firstName": "Lucky",
"lastName": "Gupta",
"email": "abc@gmail.com"
}
7.5. 删除员工
API Request
HTTP DELETE : http://localhost:8080/SpringRestExample/api/rest/employee-management/employees/1
API Response
HTTP Response code : 200
学习愉快!