大家好,这里我们将学习如何使用 Spring Boot、MyBatis 和带有 Annotation 映射的 H2 数据库开发 REST 风格的 CRUD API。您可以从我们的 Github 存储库下载源代码。
更多相关主题:
- Spring + Groovy 模板 CRUD 示例
- Spring Boot + FreeMarker + JPA - CRUD 示例
- Spring Boot + Mustache + JPA - CRUD 示例
- Spring Boot - JPA- Thymeleaf- CRUD 项目
使用的技术:
- Spring Boot 2.5.4
- Spring 5.3.9
- MyBatis 2.2.0
- Java 11
- Maven 3
完成本教程后,我们将构建什么?
我们将构建 REST API CRUD 功能:
- GET - 获取所有用户:/api/v1/users
- GET - 按 ID 获取用户:/api/v1/users/{id}
- POST - 创建用户:/api/v1/users
- PUT - 编辑用户详细信息:/api/v1/users/{id}
- DELETE - 删除用户:/api/v1/users/{id}
项目目录:
├─src
│ ├─main
│ │ ├─java
│ │ │ └─com
│ │ │ └─knf
│ │ │ └─dev
│ │ │ └─demo
│ │ │ └─springbootmybatiscrudexample
│ │ │ │ SpringbootMybatisCrudExampleApplication.java
│ │ │ │
│ │ │ ├─controller
│ │ │ │ UserController.java
│ │ │ │
│ │ │ ├─exception
│ │ │ │ CustomErrorResponse.java
│ │ │ │ GlobalExceptionHandler.java
│ │ │ │ UserIdAlreadyExistException.java
│ │ │ │ UserIdNotFoundException.java
│ │ │ │
│ │ │ ├─model
│ │ │ │ User.java
│ │ │ │
│ │ │ └─repository
│ │ │ UserRepository.java
│ │ │
│ │ └─resources
│ │ application.properties
│ │ schema.sql
Maven 依赖项(pom.xml)
放置 mybatis -spring-boot-starter , h2依赖。
<?xml version="1.0" encoding="UTF-8"?>
<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
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.5.4</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.knf.dev.demo</groupId>
<artifactId>springboot-mybatis-crud-example</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>springboot-mybatis-crud-example</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>11</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
数据库设置
我们将创建一个名为 users 的表,其中包含一些简单的列。
我们可以通过在资源中创建一个 schema.sql 文件来初始化一个模式。
create table users
(
id integer not null,
firstName varchar(255) not null,
lastName varchar(255) not null,
emailId varchar(255) not null,
primary key(id)
);
创建用户模型
package com.knf.dev.demo.springbootmybatiscrudexample.model;
public class User {
private long id;
private String firstName;
private String lastName;
private String emailId;
public User() {
}
public User(long id,String firstName,
String lastName, String emailId) {
super();
this.id=id;
this.firstName = firstName;
this.lastName = lastName;
this.emailId = emailId;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
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;
}
public String getEmailId() {
return emailId;
}
public void setEmailId(String emailId) {
this.emailId = emailId;
}
}
创建用户 MyBatis 存储库
默认情况下,MyBatis-Spring-Boot-Starter 将搜索标有 @Mapper 注释的映射器。在此示例中,我们没有使用 XML 映射。
package com.knf.dev.demo.springbootmybatiscrudexample.repository;
import com.knf.dev.demo.springbootmybatiscrudexample.model.User;
import org.apache.ibatis.annotations.*;
import java.util.List;
@Mapper
public interface UserRepository {
@Select("select * from users")
public List<User> findAll();
@Select("SELECT * FROM users WHERE id = #{id}")
public User findById(long id);
@Delete("DELETE FROM users WHERE id = #{id}")
public int deleteById(long id);
@Insert("INSERT INTO users(id, firstName, lastName,emailId) " +
" VALUES (#{id}, #{firstName}, #{lastName}, #{emailId})")
public int insert(User user);
@Update("Update users set firstName=#{firstName}, " +
" lastName=#{lastName}, emailId=#{emailId} where id=#{id}")
public int update(User user);
}
创建用户休息控制器
package com.knf.dev.demo.springbootmybatiscrudexample.controller;
import com.knf.dev.demo.springbootmybatiscrudexample.
exception.UserIdAlreadyExistException;
import com.knf.dev.demo.springbootmybatiscrudexample.
exception.UserIdNotFoundException;
import com.knf.dev.demo.springbootmybatiscrudexample.model.User;
import com.knf.dev.demo.springbootmybatiscrudexample.
repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/api/v1/")
public class UserController {
@Autowired
private UserRepository userRepository;
// get all users
@GetMapping("/users")
public List<User> getAllUsers()
{
return userRepository.findAll();
}
// create user rest API
@PostMapping("/users")
public User createUser(@RequestBody User user) {
if(userRepository.findById(user.getId())==null) {
int id = userRepository.insert(user);
return userRepository.findById(user.getId());
}else
{
throw new UserIdAlreadyExistException();
}
}
// get user by id rest api
@GetMapping("/users/{id}")
public ResponseEntity<User> getUserById(@PathVariable Long id) {
User user = userRepository.findById(id);
if(user==null)
{
throw new UserIdNotFoundException();
}
return ResponseEntity.ok(user);
}
// update user rest api
@PutMapping("/users/{id}")
public ResponseEntity<User> updateUser(@PathVariable Long id,
@RequestBody User userDetails) {
if(userRepository.update(new User(id, userDetails.getFirstName(),
userDetails.getLastName(), userDetails.getEmailId()))==0)
{
throw new UserIdNotFoundException();
}
return ResponseEntity.ok(userRepository.findById(id));
}
// delete user rest api
@DeleteMapping("/users/{id}")
public ResponseEntity<Map<String, Boolean>> deleteUser
(@PathVariable Long id) {
userRepository.deleteById(id);
Map<String, Boolean> response = new HashMap<>();
response.put("deleted", Boolean.TRUE);
return ResponseEntity.ok(response);
}
}
创建自定义异常
UserIdNotFoundException
package com.knf.dev.demo.springbootmybatiscrudexample.exception;
public class UserIdNotFoundException extends RuntimeException{
public UserIdNotFoundException()
{
super("User Id Not Found");
}
}
UserIdAlreadyExistException
package com.knf.dev.demo.springbootmybatiscrudexample.exception;
public class UserIdAlreadyExistException extends RuntimeException{
public UserIdAlreadyExistException() {
super("User Id Already Exist");
}
}
全局异常处理程序
Spring 支持通过全局异常处理程序 (@ExceptionHandler) 和控制器建议 (@ControllerAdvice) 处理异常。这启用了一种机制,使 ResponseEntity 与 @ExceptionHandler 的类型安全和灵活性一起工作。
package com.knf.dev.demo.springbootmybatiscrudexample.exception;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.context.request.WebRequest;
import java.time.LocalDateTime;
@ControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(UserIdNotFoundException.class)
public ResponseEntity<CustomErrorResponse>
globalExceptionHandler(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.NOT_FOUND.value());
return new ResponseEntity<>(errors, HttpStatus.NOT_FOUND);
}
@ExceptionHandler(UserIdAlreadyExistException.class)
public ResponseEntity<CustomErrorResponse>
globalExceptionHandler2(Exception ex, WebRequest request) {
CustomErrorResponse errors = new CustomErrorResponse();
errors.setTimestamp(LocalDateTime.now());
errors.setError(ex.getMessage());
errors.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value());
return new ResponseEntity<>
(errors, HttpStatus.INTERNAL_SERVER_ERROR);
}
}
自定义错误响应
package com.knf.dev.demo.springbootmybatiscrudexample.exception;
import com.fasterxml.jackson.annotation.JsonFormat;
import java.time.LocalDateTime;
public class CustomErrorResponse {
@JsonFormat(shape = JsonFormat.Shape.STRING,
pattern = "yyyy-MM-dd hh:mm:ss")
private LocalDateTime timestamp;
private int status;
private String error;
public LocalDateTime getTimestamp()
{
return timestamp;
}
public void setTimestamp(LocalDateTime timestamp)
{
this.timestamp = timestamp;
}
public int getStatus()
{
return status;
}
public void setStatus(int status)
{
this.status = status;
}
public String getError()
{
return error;
}
public void setError(String error)
{
this.error = error;
}
}
Spring Boot 主类
package com.knf.dev.demo.springbootmybatiscrudexample;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SpringbootMybatisCrudExampleApplication {
public static void main(String[] args) {
SpringApplication.
run(SpringbootMybatisCrudExampleApplication.class, args);
}
}
Spring Boot 应用程序的主类包含一个启动 Spring ApplicationContext 的公共静态 void main() 方法。
本地设置
第 1 步:下载或克隆源代码到本地机器。
第 2 步: mvn clean install
第 3 步:运行 Spring Boot 应用程序
mvn spring-boot:run
使用 Postman 测试 API
创建用户:
获取所有用户:
通过 ID 获取用户:
更新用户:
按 ID 删除用户: