【Java项目脚手架系列】第五篇:Spring Boot + MyBatis项目脚手架

Scroll Down

【Java项目脚手架系列】第五篇:Spring Boot + MyBatis项目脚手架

前言

在前面的文章中,我们介绍了 Spring Boot 基础项目脚手架。今天,我们将介绍 Spring Boot + MyBatis 项目脚手架,这是一个用于快速搭建企业级应用的框架。

什么是 Spring Boot + MyBatis?

Spring Boot + MyBatis 是一个强大的组合,它提供了:

  1. Spring Boot 的快速开发能力
  2. MyBatis 的灵活 SQL 映射
  3. 完整的数据库操作支持
  4. 事务管理能力
  5. 测试框架支持

技术栈

  • Spring Boot 2.7.18:核心框架
  • MyBatis 3.5.15:持久层框架
  • MySQL 8.0:关系型数据库
  • H2 Database:内存数据库,用于测试
  • JUnit 5:测试框架
  • Mockito:测试框架
  • Maven 3.9.6:项目构建工具

Spring Boot + MyBatis 项目脚手架

1. 项目结构

src
├── main
│   ├── java
│   │   └── com
│   │       └── example
│   │           └── demo
│   │               ├── DemoApplication.java
│   │               ├── config
│   │               │   └── MyBatisConfig.java
│   │               ├── controller
│   │               │   └── UserController.java
│   │               ├── mapper
│   │               │   └── UserMapper.java
│   │               ├── model
│   │               │   ├── entity
│   │               │   │   └── User.java
│   │               │   └── vo
│   │               │       └── UserVO.java
│   │               └── service
│   │                   ├── UserService.java
│   │                   └── impl
│   │                       └── UserServiceImpl.java
│   └── resources
│       ├── application.yml
│       ├── db
│       │   └── init.sql
│       └── mapper
│           └── UserMapper.xml
└── test
    ├── java
    │   └── com
    │       └── example
    │           └── demo
    │               ├── config
    │               │   └── TestConfig.java
    │               ├── controller
    │               │   └── UserControllerTest.java
    │               ├── mapper
    │               │   └── UserMapperTest.java
    │               └── service
    │                   └── UserServiceTest.java
    └── resources
        └── application-test.yml

2. 核心文件内容

2.1 pom.xml

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.example</groupId>
    <artifactId>springboot-mybatis-scaffold</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.18</version>
        <relativePath/>
    </parent>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    </properties>

    <dependencies>
        <!-- Spring Boot Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <!-- MyBatis -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>2.3.1</version>
        </dependency>

        <!-- MySQL -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.33</version>
        </dependency>

        <!-- H2 Database -->
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Boot Test -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <!-- Spring Boot DevTools -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
            <optional>true</optional>
        </dependency>

        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <configuration>
                    <excludes>
                        <exclude>
                            <groupId>org.projectlombok</groupId>
                            <artifactId>lombok</artifactId>
                        </exclude>
                    </excludes>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2.2 DemoApplication.java

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

2.3 UserController.java

package com.example.demo.controller;

import com.example.demo.model.vo.UserVO;
import com.example.demo.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

@RestController
@RequestMapping("/api/users")
public class UserController {
    private final UserService userService;

    @Autowired
    public UserController(UserService userService) {
        this.userService = userService;
    }

    @GetMapping("/{id}")
    public UserVO getUserById(@PathVariable Long id) {
        return userService.getUserById(id);
    }

    @GetMapping
    public List<UserVO> getAllUsers() {
        return userService.getAllUsers();
    }

    @PostMapping
    public UserVO createUser(@RequestBody UserVO userVO) {
        return userService.createUser(userVO);
    }

    @PutMapping("/{id}")
    public UserVO updateUser(@PathVariable Long id, @RequestBody UserVO userVO) {
        return userService.updateUser(id, userVO);
    }

    @DeleteMapping("/{id}")
    public void deleteUser(@PathVariable Long id) {
        userService.deleteUser(id);
    }
}

2.4 UserService.java

package com.example.demo.service;

import com.example.demo.model.vo.UserVO;
import java.util.List;

public interface UserService {
    UserVO getUserById(Long id);
    List<UserVO> getAllUsers();
    UserVO createUser(UserVO userVO);
    UserVO updateUser(Long id, UserVO userVO);
    void deleteUser(Long id);
}

2.5 application.yml

# Server Configuration
server:
  port: 8080
  servlet:
    context-path: /api

# Application Name
spring:
  application:
    name: springboot-mybatis-scaffold
  datasource:
    url: jdbc:mysql://localhost:3306/demo
    username: your_username
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver

# MyBatis Configuration
mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.demo.model.entity

# Logging Configuration
logging:
  level:
    root: INFO
    com.example.demo: DEBUG

3. 使用说明

  1. 克隆项目

    git clone git@gitee.com:zengqiang_wang/leecode-inteview-questions-journal.git
    
  2. 导入IDE

    • 推荐使用 IntelliJ IDEA
    • 选择 “Open as Maven Project”
    • 等待 Maven 依赖下载完成
  3. 初始化数据库

    • 创建数据库:demo
    • 执行 src/main/resources/db/init.sql 脚本
    • 修改数据库连接配置
  4. 运行项目

    mvn spring-boot:run
    
  5. 访问接口

  6. 运行测试

    # 运行所有测试
    mvn test
    
    # 运行特定测试类
    mvn test -Dtest=UserControllerTest
    
    # 运行特定测试方法
    mvn test -Dtest=UserControllerTest#testGetUserById
    

4. 单元测试

项目包含了完整的单元测试示例,展示了如何测试 Spring Boot + MyBatis 应用的不同组件:

  1. 服务层测试

    • 使用 JUnit 5 进行基础单元测试
    • 使用 Mockito 模拟依赖
    • 测试正常和边界情况
    • 示例:UserServiceTest.java
  2. Mapper 层测试

    • 使用 H2 内存数据库
    • 测试数据库操作
    • 事务自动回滚
    • 示例:UserMapperTest.java
  3. 控制器层测试

    • 使用 MockMvc 测试 HTTP 接口
    • 验证请求和响应
    • 示例:UserControllerTest.java

5. 最佳实践

  1. 控制器设计

    • 使用 RESTful 风格
    • 合理使用请求方法
    • 统一响应格式
    • 参数验证
  2. 服务层设计

    • 业务逻辑封装
    • 事务管理
    • 异常处理
    • 数据转换
  3. 数据访问层设计

    • 使用 MyBatis 注解或 XML
    • 动态 SQL 支持
    • 分页查询
    • 缓存配置
  4. 配置管理

    • 使用配置文件
    • 环境隔离
    • 敏感信息保护
    • 数据库连接池

6. 常见问题

  1. 数据库连接问题

    • 检查数据库配置
    • 确保数据库服务运行
    • 验证用户名密码
    • 检查连接池配置
  2. MyBatis 配置问题

    • 检查 Mapper 扫描路径
    • 验证 XML 文件位置
    • 确认 SQL 语句正确性
    • 检查类型别名配置
  3. 事务管理问题

    • 检查事务注解
    • 验证事务传播行为
    • 确认事务隔离级别
    • 处理事务回滚
  4. MySQL 相关问题

    • 问题:本地未安装 MySQL

      • 原因:开发环境缺少 MySQL 数据库
      • 解决方案:
        1. 安装 MySQL 8.0
        2. 或使用 Docker 运行 MySQL:
          docker run --name mysql -e MYSQL_ROOT_PASSWORD=root -p 3306:3306 -d mysql:8.0
          
        3. 或使用 H2 数据库替代(仅用于开发环境)
    • 问题:MySQL 连接失败

      • 原因:MySQL 服务未启动或配置错误
      • 解决方案:
        spring:
          datasource:
            url: jdbc:mysql://localhost:3306/demo?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=Asia/Shanghai
            username: your_username
            password: your_password
        
  5. H2 数据库问题

    • 问题:表名冲突

      • 原因:user 是 H2 数据库的保留关键字
      • 解决方案:将表名改为 t_user 或其他非保留关键字
      • 示例:
        -- 修改前
        CREATE TABLE user (
            id BIGINT PRIMARY KEY,
            username VARCHAR(50)
        );
        
        -- 修改后
        CREATE TABLE t_user (
            id BIGINT PRIMARY KEY,
            username VARCHAR(50)
        );
        
    • 问题:SQL 语法不兼容

      • 原因:H2 与 MySQL 的 SQL 语法存在差异
      • 解决方案:
        1. 在 H2 连接 URL 中添加 MySQL 兼容模式:
          spring:
            datasource:
              url: jdbc:h2:mem:testdb;MODE=MySQL;DATABASE_TO_LOWER=TRUE;CASE_INSENSITIVE_IDENTIFIERS=TRUE
          
        2. 使用 H2 兼容的 SQL 语法
        3. 为测试环境准备单独的 SQL 文件
    • 问题:测试数据未持久化

      • 原因:H2 内存数据库在应用重启后数据会丢失
      • 解决方案:
        1. 使用文件模式而不是内存模式
        2. 在测试类中初始化测试数据
        3. 使用 @Transactional 确保测试数据回滚
    • 问题:H2 控制台访问失败

      • 原因:H2 控制台未启用或配置错误
      • 解决方案:
        spring:
          h2:
            console:
              enabled: true
              path: /h2-console
          datasource:
            url: jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1
            username: sa
            password:
        
  6. 开发环境配置建议

    • 使用 H2 数据库进行本地开发
    • 配置多环境支持
    • 分离开发和生产配置
    • 使用 Docker 容器化数据库

总结

Spring Boot + MyBatis 脚手架提供了一个完整的企业级应用开发基础,包含了必要的配置和示例代码。通过这个项目,你可以:

  1. 快速搭建 Web 应用
  2. 实现数据库操作
  3. 进行单元测试
  4. 使用开发工具

明日预告

明天我们将介绍 Spring Boot + JPA 项目脚手架,主要内容包括:

  • JPA 与 Spring Boot 的集成
  • 实体关系映射
  • 数据访问层设计
  • 事务管理
  • 分页查询实现
  • 单元测试示例

敬请期待!