当前位置:首页 > 技术 > 正文内容

Spring Boot 集成 MyBatis 的核心方案与自动化开发实践

访客 技术 2026年8月9日 1

环境准备与核心依赖

在 Spring Boot 项目中引入 MyBatis 需要配置持久层 starter、数据库驱动以及必要的工具类。推荐使用 Lombok 简化实体类样板代码,并引入热部署插件提升开发效率。

<dependencies>
    <!-- Web 基础环境 -->
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <!-- MyBatis 集成 Starter -->
    <dependency>
        <groupId>org.mybatis.spring.boot</groupId>
        <artifactId>mybatis-spring-boot-starter</artifactId>
        <version>2.3.0</version>
    </dependency>

    <!-- MySQL 连接器 -->
    <dependency>
        <groupId>com.mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
        <scope>runtime</scope>
    </dependency>

    <!-- 代码简化与热更新 -->
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
    </dependency>
</dependencies>

全局配置文件设计

通过 YAML 格式集中管理应用参数。开启驼峰命名自动映射、配置数据源信息,并指定 MyBatis 的映射文件路径(XML 方案时生效)。

server:
  port: 8080
  servlet:
    context-path: /api

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/demo_db?useSSL=false&serverTimezone=Asia/Shanghai
    username: db_admin
    password: secure_pwd
    driver-class-name: com.mysql.cj.jdbc.Driver
  jackson:
    date-format: yyyy-MM-dd HH:mm:ss
    time-zone: GMT+8

mybatis:
  mapper-locations: classpath:/mappers/**/*.xml
  config-location: classpath:/mybatis-config.xml
  configuration:
    map-underscore-to-camel-case: true

基础模型与响应封装

统一接口返回结构有助于前端标准化处理。结合 Lombok 注解可大幅减少 Getter/Setter 代码量。

@Data
@AllArgsConstructor
@NoArgsConstructor
public class ApiResponse<T> {
    private int code;
    private String msg;
    private T payload;

    public static ApiResponse success(T data) {
        return new ApiResponse(200, "执行成功", data);
    }

    public static ApiResponse fail(String reason) {
        return new ApiResponse(400, reason, null);
    }
}
@Data
public class Member {
    private Integer id;
    private String account;
    private String credential;
    private LocalDateTime createdAt;
}

数据表结构初始化

CREATE TABLE `sys_member` (
  `id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '主键标识',
  `account` VARCHAR(64) DEFAULT NULL COMMENT '登录账号',
  `credential` VARCHAR(255) DEFAULT NULL COMMENT '加密凭证',
  `created_at` DATETIME DEFAULT NULL COMMENT '创建时间',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='会员基础信息表';

控制层与业务层架构

遵循分层原则,Controller 仅负责参数接收与响应封装,Service 处理业务逻辑与事务边界。

@RestController
@RequestMapping("/members")
public class MemberEndpoint {

    @Autowired
    private MemberManager memberService;

    @PostMapping("/save")
    public ApiResponse save(@RequestBody Member entity) {
        return memberService.persist(entity);
    }

    @GetMapping("/find")
    public ApiResponse query(@RequestParam(required = false) Integer id) {
        Member criteria = new Member();
        criteria.setId(id);
        return memberService.locate(criteria);
    }
}
@Service
public class MemberManager {

    @Autowired
    private MemberRepository memberDao;

    public ApiResponse persist(Member entity) {
        int affected = memberDao.insert(entity);
        return affected > 0 ? ApiResponse.success(entity) : ApiResponse.fail("写入失败");
    }

    public ApiResponse locate(Member criteria) {
        Member result = memberDao.select(criteria);
        return result != null ? ApiResponse.success(result) : ApiResponse.fail("未找到记录");
    }
}

数据访问层实现方案

方案一:注解驱动模式

将 SQL 语句直接声明在接口方法上,适合简单查询。需注意参数绑定符的差异:`#{}` 会进行预编译防注入,适用于值传递;`${}` 为纯字符串拼接,适用于动态表名或字段名排序。

@Mapper
public interface MemberRepository {

    @Insert("INSERT INTO sys_member(account, credential, created_at) VALUES(#{account}, #{credential}, #{createdAt})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(Member entity);

    @Select("SELECT * FROM sys_member WHERE id = #{id}")
    Member select(Member criteria);

    @Delete("DELETE FROM sys_member WHERE id = #{id}")
    int delete(Member criteria);
}

方案二:XML 映射模式

将 SQL 剥离至独立配置文件,便于复杂查询维护。接口层仅保留方法签名。

@Mapper
public interface MemberRepository {
    int insert(Member entity);
    Member select(Member criteria);
    int delete(Member criteria);
}
<?xml version="1.0" encoding="UTF-8" ?>
<mapper namespace="com.example.dao.MemberRepository">
    <insert id="insert" useGeneratedKeys="true" keyProperty="id" parameterType="com.example.model.Member">
        INSERT INTO sys_member(account, credential, created_at) 
        VALUES(#{account}, #{credential}, #{createdAt})
    </insert>

    <select id="select" parameterType="com.example.model.Member" resultType="com.example.model.Member">
        SELECT id, account, credential, created_at 
        FROM sys_member 
        WHERE id = #{id}
    </select>

    <delete id="delete" parameterType="com.example.model.Member">
        DELETE FROM sys_member WHERE id = #{id}
    </delete>
</mapper>

逆向工程自动化生成

针对多表系统,手动编写 CRUD 效率较低。MyBatis Generator (MBG) 可根据数据库表结构自动生成实体类、Mapper 接口及 XML 映射文件。核心在于编写生成器配置文件并执行驱动类。

<generatorConfiguration>
    <context id="MyBatisGenerator" targetRuntime="MyBatis3">
        <commentGenerator>
            <property name="suppressAllComments" value="true"/>
        </commentGenerator>
        <jdbcConnection driverClass="com.mysql.cj.jdbc.Driver"
                        connectionURL="jdbc:mysql://127.0.0.1:3306/demo_db"
                        userId="db_admin" password="secure_pwd"/>
        <javaModelGenerator targetPackage="com.example.model" targetProject="./src/main/java">
            <property name="trimStrings" value="true"/>
        </javaModelGenerator>
        <sqlMapGenerator targetPackage="mappers" targetProject="./src/main/resources"/>
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.dao" targetProject="./src/main/java"/>
        <table tableName="sys_member" domainObjectName="Member"/>
    </context>
</generatorConfiguration>
public class GeneratorRunner {
    public static void main(String[] args) throws Exception {
        List<String> warnings = new ArrayList<>();
        File configFile = new File("src/main/resources/generatorConfig.xml");
        ConfigurationParser cp = new ConfigurationParser(warnings);
        Configuration config = cp.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(true);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        System.out.println("代码生成完毕,请检查目标目录。");
    }
}

执行后,框架会自动处理字段命名转换:数据库下划线格式(如 `created_at`)将映射为驼峰属性(`createdAt`),并生成配套的 `Example` 查询构建器,支持链式条件拼装。

集成 PageHelper 实现分页

物理分页是生产环境的刚需。PageHelper 通过拦截器机制在目标 SQL 后自动追加 `LIMIT` 语句,支持主流关系型数据库。

<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.7</version>
</dependency>

在 `mybatis-config.xml` 中声明拦截器插件:

<?xml version="1.0" encoding="UTF-8" ?>
<configuration>
    <plugins>
        <plugin interceptor="com.github.pagehelper.PageInterceptor">
            <property name="helperDialect" value="mysql"/>
            <property name="reasonable" value="true"/>
        </plugin>
    </plugins>
</configuration>

业务调用示例:

// 启动分页,参数分别为页码与每页大小
PageHelper.startPage(currentPage, pageSize);
// 仅拦截紧随其后的第一条 SELECT 查询
List<Member> records = memberDao.select(criteria);
// 封装分页元数据
PageInfo<Member> pageData = new PageInfo<>(records);

底层原理依赖于 `ThreadLocal` 实现线程隔离,拦截器获取当前线程的 SQL 语句后动态重写为带分页参数的语句,处理完毕后再清理上下文。需注意:分页指令仅对紧接 `startPage` 的查询生效,且不支持 `FOR UPDATE` 或复杂嵌套关联查询的分页场景。

标签: springboot

相关文章

Linux crontab 详解

1) crontab 是什么cron 是 Linux 的定时任务守护进程;crontab 是用来编辑/查看“按时间周期执行命令”的表(cron table)。常见两类:用户 crontab:每个用户一份(crontab -e 编辑)系统级 crontab / cron.d:可指定执行用户(/etc/crontab、/etc/cron.d/*)2) crontab 时间...

富文本里可以允许的 HTML 属性

一、所有标签默认允许的安全属性(极少)class        (可选)id           (通常建议禁用)title️ 注意:id 容易被滥用做锚点注入,很多系统直接禁用class 允许的话最好只允许固定前缀(如 editor-*)二、a 标签允许属性<a href="" t...

Mac 安装 Node.js 指南

方法一:通过官网安装包(最简单,适合初学者)如果你只是想快速安装并开始使用,这是最直接的方法。访问 Node.js 官网。页面会显示两个版本:LTS (Recommended For Most Users):长期支持版,最稳定。建议选这个。Current:最新特性版,包含最新功能但可能不够稳定。下载 .pkg 安装包并运行。按照安装向导点击“下一步”即可完成。方法二:使用 Homebrew 安装(...

Dom\HTML_NO_DEFAULT_NS 的副作用:自动加闭合标签

在使用Dom\HTMLDocument时,Dom\HTML_NO_DEFAULT_NS 将禁止在解析过程中设置元素的命名空间, 此设置是为了与DOMDocument向后兼容而存在的。当使用它时,已知的一个副作用就是:自动加闭合标签例如 </img> 为什么会这样?当你使用:Dom\HTML_NO_DEFAULT_NS文档会变成 无命名空间模式,此时内部更接近 XML...

Laravel 事件和监听器创建

在 Laravel 中,使用 Artisan 命令创建 Events(事件) 和 Listeners(监听器) 是非常高效的。你可以通过以下几种方式来实现:1. 手动创建单个 Event如果你只想创建一个事件类,可以使用 make:event 命令:Bashphp artisan make:event UserRegistered执行后,文件将生成在 app/Even...

自定义域名解析神器 dnsmasq

什么是 dnsmasq?dnsmasq 是一个轻量级、功能强大的网络服务工具,专为小型和中等规模网络设计。它是一个综合的网络基础设施解决方案[1]。dnsmasq 能做什么?功能说明应用场景DNS 转发与缓存将 DNS 查询转发到上游服务器(ISP、Google DNS 等),并在本地缓存结果加快 DNS 查询速度,减少外部 DNS 流量本地 DNS解析本地网络设备的主机名,无需编辑&n...

发表评论

访客

◎欢迎参与讨论,请在这里发表您的看法和观点。