SpringBoot 整合 MyBatis 完整实战

SpringBoot + MyBatis 可以说是国内后端开发最经典、最常用的组合了。本篇文章就来介绍一下SpringBoot如何整合MyBatis,实现数据表的增删改查。


一、引言

SpringBoot 整合 MyBatis 是国内 Java 后端最主流的持久层方案:

  • • 灵活可控,SQL 可优化、可维护

  • • 适合复杂查询、多表关联、统计报表

  • • 配合 XML 或注解开发效率极高

  • • 分页、事务、缓存生态成熟

这篇文章会带你完整实现:

    1. 依赖与配置
    1. 数据库建表
    1. 实体类、Mapper接口、XML映射
    1. 单表增删改查
    1. 多条件动态查询
    1. 分页查询(PageHelper)
    1. Service 事务控制
    1. Controller 接口统一返回
    1. 真实开发规范 + 高频坑点解决

二、引入完整依赖(pom.xml)

包含:MyBatis启动器、MySQL驱动、分页插件、Lombok、连接池

go 复制代码
<!-- SpringBoot Web -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

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

<!-- MySQL 驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

<!-- 分页插件 -->
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.7</version>
</dependency>

<!-- Lombok 简化实体 -->
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>

三、application.yml 完整配置

go 复制代码
server:
  port:8080

spring:
# 数据源配置
datasource:
    url:jdbc:mysql://localhost:3306/testdb?useUnicode=true&characterEncoding=utf-8&serverTimezone=Asia/Shanghai&allowMultiQueries=true
    username:root
    password:123456
    driver-class-name:com.mysql.cj.jdbc.Driver

# MyBatis 配置
mybatis:
# XML 文件路径
mapper-locations:classpath:mapper/*.xml
# 实体类别名
type-aliases-package:com.demo.entity
configuration:
    # 下划线自动转驼峰(必须开)
    map-underscore-to-camel-case:true
    # 打印SQL(开发环境打开)
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl

四、建表 SQL(user 表)

go 复制代码
CREATE TABLE `user` (
  `id` bigintNOT NULL AUTO_INCREMENT COMMENT '主键ID',
  `username` varchar(50) NOT NULL COMMENT '用户名',
  `password` varchar(100) DEFAULTNULL COMMENT '密码',
  `age` intDEFAULTNULL COMMENT '年龄',
  `email` varchar(50) DEFAULTNULL COMMENT '邮箱',
  `create_time` datetime DEFAULTCURRENT_TIMESTAMP COMMENT '创建时间',
  `update_time` datetime DEFAULTCURRENT_TIMESTAMPONUPDATECURRENT_TIMESTAMP COMMENT '更新时间',
  `deleted` tinyint DEFAULT0 COMMENT '逻辑删除 0未删 1已删',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

五、实体类(Entity)

go 复制代码
package com.demo.entity;

import lombok.Data;
import java.time.LocalDateTime;

@Data
publicclassUser {
    private Long id;
    private String username;
    private String password;
    private Integer age;
    private String email;
    private LocalDateTime createTime;
    private LocalDateTime updateTime;
    private Integer deleted;
}

六、Mapper 接口(数据访问层)

包含:CRUD + 多条件查询 + 分页

go 复制代码
package com.demo.mapper;

import com.demo.entity.User;
import org.apache.ibatis.annotations.Param;
import java.util.List;

publicinterfaceUserMapper {

    // 新增
    intinsert(User user);

    // 根据ID删除
    intdeleteById(Long id);

    // 根据ID修改
    intupdateById(User user);

    // 根据ID查询
    User selectById(Long id);

    // 查询全部
    List<User> selectAll();

    // 多条件动态查询
    List<User> selectByCondition(@Param("username") String username,
                                @Param("age") Integer age);
}

启动类添加 Mapper 扫描

go 复制代码
@SpringBootApplication
@MapperScan("com.demo.mapper")
public class DemoApplication {
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

七、MyBatis XML 映射文件

resources/mapper/UserMapper.xml

go 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.demo.mapper.UserMapper">

    <!-- 新增 -->
    <insert id="insert">
        insert into user(username,password,age,email)
        values(#{username},#{password},#{age},#{email})
    </insert>

    <!-- 删除 -->
    <delete id="deleteById">
        delete from user where id=#{id}
    </delete>

    <!-- 修改 -->
    <update id="updateById">
        update user
        set username=#{username},age=#{age},email=#{email}
        where id=#{id}
    </update>

    <!-- 根据ID查询 -->
    <select id="selectById" resultType="User">
        select * from user where id=#{id} and deleted=0
    </select>

    <!-- 查询全部 -->
    <select id="selectAll" resultType="User">
        select * from user where deleted=0
    </select>

    <!-- 多条件动态查询 -->
    <select id="selectByCondition" resultType="User">
        select * from user
        <where>
            deleted=0
            <if test="username != null and username != ''">
                and username like concat('%',#{username},'%')
            </if>
            <if test="age != null">
                and age = #{age}
            </if>
        </where>
    </select>

</mapper>

八、Service 层(业务逻辑 + 事务)

8.1 UserService 接口

go 复制代码
package com.demo.service;

import com.demo.entity.User;
import com.github.pagehelper.PageInfo;
import java.util.List;

publicinterfaceUserService {
    // 新增
    booleanadd(User user);
    // 删除
    booleandelete(Long id);
    // 修改
    booleanupdate(User user);
    // 根据ID查询
    User getById(Long id);
    // 查询全部
    List<User> list();
    // 多条件查询
    List<User> search(String username, Integer age);
    // 分页查询
    PageInfo<User> page(Integer pageNum, Integer pageSize);
}

8.2 UserServiceImpl 实现类

go 复制代码
package com.demo.service.impl;

import com.demo.entity.User;
import com.demo.mapper.UserMapper;
import com.demo.service.UserService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.List;

@Service
publicclassUserServiceImplimplementsUserService {

    @Resource
    private UserMapper userMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    publicbooleanadd(User user) {
        return userMapper.insert(user) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    publicbooleandelete(Long id) {
        return userMapper.deleteById(id) > 0;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    publicbooleanupdate(User user) {
        return userMapper.updateById(user) > 0;
    }

    @Override
    public User getById(Long id) {
        return userMapper.selectById(id);
    }

    @Override
    public List<User> list() {
        return userMapper.selectAll();
    }

    @Override
    public List<User> search(String username, Integer age) {
        return userMapper.selectByCondition(username, age);
    }

    @Override
    public PageInfo<User> page(Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        List<User> list = userMapper.selectAll();
        returnnewPageInfo<>(list);
    }
}

九、Controller 层(接口)

go 复制代码
package com.demo.controller;

import com.demo.common.Result;
import com.demo.entity.User;
import com.demo.service.UserService;
import com.github.pagehelper.PageInfo;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.List;

@RestController
@RequestMapping("/user")
publicclassUserController {

    @Resource
    private UserService userService;

    // 新增
    @PostMapping("/add")
    public Result add(@RequestBody User user) {
        userService.add(user);
        return Result.success("新增成功");
    }

    // 删除
    @DeleteMapping("/delete/{id}")
    public Result delete(@PathVariable Long id) {
        userService.delete(id);
        return Result.success("删除成功");
    }

    // 修改
    @PutMapping("/update")
    public Result update(@RequestBody User user) {
        userService.update(user);
        return Result.success("修改成功");
    }

    // 单个查询
    @GetMapping("/detail/{id}")
    public Result detail(@PathVariable Long id) {
        return Result.success(userService.getById(id));
    }

    // 列表
    @GetMapping("/list")
    public Result list() {
        return Result.success(userService.list());
    }

    // 多条件搜索
    @GetMapping("/search")
    public Result search(
            @RequestParam(required = false) String username,
            @RequestParam(required = false) Integer age) {
        return Result.success(userService.search(username, age));
    }

    // 分页
    @GetMapping("/page")
    public Result page(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize) {
        PageInfo<User> page = userService.page(pageNum, pageSize);
        return Result.success(page);
    }
}

十、统一返回结果类

go 复制代码
package com.demo.common;

import lombok.Data;

@Data
publicclassResult<T> {
    privateint code;
    private String msg;
    private T data;

    publicstatic <T> Result<T> success(T data) {
        Result<T> r = newResult<>();
        r.setCode(200);
        r.setMsg("操作成功");
        r.setData(data);
        return r;
    }

    publicstatic <T> Result<T> success(String msg) {
        Result<T> r = newResult<>();
        r.setCode(200);
        r.setMsg(msg);
        return r;
    }
}

十一、重点功能

1. 分页查询(PageHelper)

  • • 必须在查询前一行使用

  • • 自动拼接 LIMIT,无需改 SQL

  • • 返回 PageInfo 包含:总条数、总页数、当前页、数据列表

2. 动态 SQL(if / where / foreach)

适合多条件搜索、后台管理系统查询。

3. 事务控制

@Transactional 任何异常自动回滚。

4. 下划线自动转驼峰

map-underscore-to-camel-case: true
create_timecreateTime


十二、注意事项

    1. Mapper 注入失败

    启动类必须加 @MapperScan

    1. XML 绑定异常

    namespace 必须和 Mapper 全类名一致

    1. 分页不生效

    PageHelper.startPage 必须紧跟查询

    1. SQL 语句报错

    XML 中不能直接写 &<,需要转义

    1. 字段映射不上

    开启驼峰转换

    1. 参数多个时必须用 @Param

    否则 MyBatis 识别不到


相关推荐
helx822 小时前
SpringBoot中自定义Starter
java·spring boot·后端
_MyFavorite_2 小时前
JAVA重点基础、进阶知识及易错点总结(31)设计模式基础(单例、工厂)
java·开发语言·设计模式
ILYT NCTR3 小时前
SpringSecurity 实现token 认证
java
rleS IONS3 小时前
SpringBoot获取bean的几种方式
java·spring boot·后端
014-code3 小时前
Java SPI 实战:ServiceLoader 的正确打开方式(含类加载器坑)
java·开发语言
lifewange3 小时前
Go语言-开源编程语言
开发语言·后端·golang
程序员榴莲3 小时前
Javase(七):继承
java
wwj888wwj3 小时前
Docker基础(复习)
java·linux·运维·docker
白毛大侠3 小时前
深入理解 Go:用户态和内核态
开发语言·后端·golang
qq_5470261793 小时前
LangChain 工具调用(Tool Calling)
java·大数据·langchain