建好了表,还在手动写CRUD的xml?兄弟,真得学习MBG了!

还在手动写CRUD的XML?兄弟,真得学习MBG了!

兄弟,如果你还在为MyBatis手写一堆XML的CRUD操作累得焦头烂额,那真得停下来看看MyBatis Generator(简称MBG)了!它能帮你自动生成Model、Mapper接口和XML配置文件,极大提升开发效率。本文将基于Spring Boot 3 + MyBatis 3的技术栈,带你从建表SQL到MBG配置,再到项目结构和手动写DAO的场景,全面解析MBG的用法和注意事项。话不多说,直接上干货!


一、建表SQL:先把数据库结构搭好

我们以一个简单的电商场景为例,创建三张表:user(用户信息)、product(商品信息)和order(订单信息),并建立适当的外键关系。

sql 复制代码
-- 创建用户表
CREATE TABLE `user` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '用户ID',
  `username` VARCHAR(50) NOT NULL COMMENT '用户名',
  `email` VARCHAR(100) NOT NULL COMMENT '邮箱',
  `created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_username` (`username`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户表';

-- 创建商品表
CREATE TABLE `product` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '商品ID',
  `name` VARCHAR(100) NOT NULL COMMENT '商品名称',
  `price` DECIMAL(10, 2) NOT NULL COMMENT '价格',
  `stock` INT NOT NULL COMMENT '库存',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='商品表';

-- 创建订单表
CREATE TABLE `order` (
  `id` BIGINT NOT NULL AUTO_INCREMENT COMMENT '订单ID',
  `user_id` BIGINT NOT NULL COMMENT '用户ID',
  `product_id` BIGINT NOT NULL COMMENT '商品ID',
  `quantity` INT NOT NULL COMMENT '购买数量',
  `order_time` TIMESTAMP DEFAULT CURRENT_TIMESTAMP COMMENT '下单时间',
  PRIMARY KEY (`id`),
  FOREIGN KEY (`user_id`) REFERENCES `user` (`id`),
  FOREIGN KEY (`product_id`) REFERENCES `product` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='订单表';

这些表结构简单明了,包含了主键、外键和常见字段类型,适合展示MBG的生成效果。


二、项目结构:MBG生成什么,手动写什么?

在使用MBG之前,先来看看项目的目录结构,方便你理解哪些文件是MBG自动生成的,哪些需要我们手动补充。

bash 复制代码
project-root
├── src
│   ├── main
│   │   ├── java
│   │   │   └── com
│   │   │       └── example
│   │   │           ├── Application.java                # Spring Boot 启动类
│   │   │           ├── config
│   │   │           │   └── MyBatisConfig.java          # MyBatis 配置类
│   │   │           ├── dao
│   │   │           │   ├── UserMapper.java             # MBG自动生成
│   │   │           │   ├── ProductMapper.java          # MBG自动生成
│   │   │           │   ├── OrderMapper.java            # MBG自动生成
│   │   │           │   └── CustomOrderDao.java         # 手动编写的DAO
│   │   │           ├── model
│   │   │           │   ├── User.java                   # MBG自动生成
│   │   │           │   ├── UserExample.java            # MBG自动生成
│   │   │           │   ├── Product.java                # MBG自动生成
│   │   │           │   ├── ProductExample.java         # MBG自动生成
│   │   │           │   ├── Order.java                  # MBG自动生成
│   │   │           │   └── OrderExample.java           # MBG自动生成
│   │   │           ├── service
│   │   │           │   ├── UserService.java            # 手动编写
│   │   │           │   ├── ProductService.java         # 手动编写
│   │   │           │   └── OrderService.java           # 手动编写
│   │   │           └── controller
│   │   │               └── OrderController.java        # 手动编写
│   │   └── resources
│   │       ├── mapper
│   │       │   ├── UserMapper.xml                     # MBG自动生成
│   │       │   ├── ProductMapper.xml                  # MBG自动生成
│   │       │   └── OrderMapper.xml                    # MBG自动生成
│   │       ├── application.yml                        # Spring Boot 配置文件
│   │       └── generatorConfig.xml                    # MBG配置文件
│   └── test
│       └── java
│           └── com
│               └── example
│                   └── ApplicationTests.java           # 测试类
├── pom.xml                                            # Maven配置文件
└── README.md

说明

  • MBG自动生成UserMapper.javaProductMapper.javaOrderMapper.java(Mapper接口),User.javaProduct.javaOrder.java(实体类),UserExample.javaProductExample.javaOrderExample.java(条件查询类),以及mapper目录下的XML文件。
  • 手动编写CustomOrderDao.java(自定义DAO,处理复杂业务逻辑)、Service层、Controller层,以及Spring Boot的配置文件和启动类。

三、MBG配置:让代码自动生成

MBG的核心是generatorConfig.xml,我们需要配置数据库连接、生成规则和输出路径。下面是一个详细的配置文件,带注释说明每个部分的作用。

xml 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">

<generatorConfiguration>
    <!-- 数据库驱动:指定MySQL驱动的JAR包路径(需提前放入项目目录) -->
    <classPathEntry location="mysql-connector-java-8.0.30.jar" />

    <!-- 数据库连接配置 -->
    <context id="MySQLTables" targetRuntime="MyBatis3">
        <!-- 数据库连接信息 -->
        <jdbcConnection
            driverClass="com.mysql.cj.jdbc.Driver"
            connectionURL="jdbc:mysql://localhost:3306/mbg_demo?useSSL=false&amp;serverTimezone=UTC"
            userId="root"
            password="your_password" />

        <!-- Java模型生成配置 -->
        <javaModelGenerator targetPackage="com.example.model" targetProject="src/main/java">
            <!-- 是否在当前路径下生成子包 -->
            <property name="enableSubPackages" value="true" />
            <!-- 是否对模型添加构造函数 -->
            <property name="constructorBased" value="false" />
            <!-- 是否对列名进行trim操作 -->
            <property name="trimStrings" value="true" />
        </javaModelGenerator>

        <!-- SQL映射文件(XML)生成配置 -->
        <sqlMapGenerator targetPackage="mapper" targetProject="src/main/resources">
            <property name="enableSubPackages" value="true" />
        </sqlMapGenerator>

        <!-- Mapper接口生成配置 -->
        <javaClientGenerator type="XMLMAPPER" targetPackage="com.example.dao" targetProject="src/main/java">
            <property name="enableSubPackages" value="true" />
        </javaClientGenerator>

        <!-- 指定表和生成规则 -->
        <table tableName="user" domainObjectName="User" enableCountByExample="true"
               enableUpdateByExample="true" enableDeleteByExample="true"
               enableSelectByExample="true" selectByExampleQueryId="true">
            <!-- 是否生成Example类 -->
            <generatedKey column="id" sqlStatement="MySQL" identity="true" />
        </table>
        <table tableName="product" domainObjectName="Product" enableCountByExample="true"
               enableUpdateByExample="true" enableDeleteByExample="true"
               enableSelectByExample="true" selectByExampleQueryId="true">
            <generatedKey column="id" sqlStatement="MySQL" identity="true" />
        </table>
        <table tableName="order" domainObjectName="Order" enableCountByExample="true"
               enableUpdateByExample="true" enableDeleteByExample="true"
               enableSelectByExample="true" selectByExampleQueryId="true">
            <generatedKey column="id" sqlStatement="MySQL" identity="true" />
        </table>
    </context>
</generatorConfiguration>

关键点

  1. 数据库驱动 :需要下载mysql-connector-java并指定路径,或者通过Maven依赖引入。
  2. 生成路径javaModelGeneratorsqlMapGeneratorjavaClientGenerator分别控制Model、XML和Mapper接口的输出位置。
  3. 表配置 :通过<table>标签指定要生成的表,generatedKey用于设置主键自增。
  4. Example支持enable*ByExample属性开启条件查询功能,生成Example类。

运行MBG的方式:

  • 命令行java -jar mybatis-generator-core-1.4.0.jar -configfile generatorConfig.xml -overwrite
  • Maven插件 :配置mybatis-generator-maven-plugin并运行mvn mybatis-generator:generate

四、Spring Boot配置:整合MyBatis

为了让Spring Boot正常使用MyBatis和MBG生成的代码,我们需要配置application.yml和MyBatis配置类。

1. application.yml

yaml 复制代码
spring:
  datasource:
    url: jdbc:mysql://localhost:3306/mbg_demo?useSSL=false&serverTimezone=UTC
    username: root
    password: your_password
    driver-class-name: com.mysql.cj.jdbc.Driver

mybatis:
  mapper-locations: classpath:mapper/*.xml
  type-aliases-package: com.example.model

说明

  • spring.datasource:配置数据库连接。
  • mybatis.mapper-locations:指定MBG生成的XML文件路径。
  • mybatis.type-aliases-package:指定Model类的包路径,简化XML中的类型引用。

2. MyBatisConfig.java

kotlin 复制代码
package com.example.config;

import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Configuration;

@Configuration
@MapperScan("com.example.dao")
public class MyBatisConfig {
    // 配置MyBatis的Mapper扫描路径
}

说明

  • @MapperScan注解自动扫描com.example.dao包下的Mapper接口,省去手动添加@Mapper注解的麻烦。

五、MBG的Example类:灵活查询的利器

MBG生成的Example类是条件查询的核心,用于动态构建SQL的WHERE条件。比如,查询某个用户的订单:

ini 复制代码
OrderExample example = new OrderExample();
example.createCriteria()
    .andUserIdEqualTo(1L)
    .andOrderTimeGreaterThan(new Date(System.currentTimeMillis() - 24 * 60 * 60 * 1000));
List<Order> orders = orderMapper.selectByExample(example);

Example的用处

  1. 动态查询 :通过createCriteria()or()方法,可以灵活组合查询条件。
  2. 批量操作 :支持updateByExampledeleteByExample等批量操作。
  3. 分页支持 :结合RowBounds实现分页查询。

使用场景

  • 复杂条件查询(如多字段组合、模糊查询)。
  • 批量更新或删除(如更新某类用户的状态)。

六、MBG的缺陷和手动写DAO的场景

虽然MBG很强大,但它也有局限性,有些场景需要我们手动写DAO和XML。

MBG的缺陷

  1. 复杂SQL不支持:MBG只生成简单的CRUD,复杂的多表联查、子查询或存储过程需要手动实现。
  2. 业务逻辑耦合:MBG生成的代码是通用的,难以直接处理业务逻辑(如订单状态流转)。
  3. XML维护问题:如果表结构变更,MBG重新生成会覆盖自定义的XML内容(除非配置插件)。

什么时候需要手动写DAO?

  1. 多表关联查询 :比如查询订单详情,需关联userproduct表。
  2. 复杂业务逻辑:如订单创建时需要检查库存、更新用户积分等。
  3. 自定义SQL:如统计报表、复杂聚合查询。
  4. 性能优化:MBG生成的SQL可能不够高效,手动优化能减少查询开销。

示例:手动实现的CustomOrderDao

kotlin 复制代码
package com.example.dao;

import com.example.model.Order;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;

import java.util.List;

@Mapper
public interface CustomOrderDao {
    @Select("SELECT o.*, u.username, p.name AS product_name " +
            "FROM `order` o " +
            "JOIN `user` u ON o.user_id = u.id " +
            "JOIN `product` p ON o.product_id = p.id " +
            "WHERE o.user_id = #{userId}")
    List<Order> selectOrderDetailsByUserId(Long userId);
}

对应的XML(可选)

如果不用注解,可以在resources/mapper/CustomOrderMapper.xml中定义:

xml 复制代码
<?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.example.dao.CustomOrderDao">
    <select id="selectOrderDetailsByUserId" resultType="com.example.model.Order">
        SELECT o.*, u.username, p.name AS product_name
        FROM `order` o
        JOIN `user` u ON o.user_id = u.id
        JOIN `product` p ON o.product_id = p.id
        WHERE o.user_id = #{userId}
    </select>
</mapper>

七、总结:MBG的正确打开方式

MBG是解放双手的神器,能自动生成80%的CRUD代码,但它不是万能的。简单单表操作交给MBG,复杂业务逻辑和多表查询还是得靠手动DAO。合理结合MBG的Example类和自定义DAO,能让你的代码既高效又灵活。

小建议

  • 配置好generatorConfig.xml,跑一把MBG,感受自动化的快感。
  • 对于复杂业务,写个Custom*Dao专门处理,别和MBG生成的代码混在一起。
  • 善用Example类,动态查询省心又省力。

兄弟,赶紧把MBG用起来,告别手写XML的苦日子吧!如果有啥问题,欢迎留言讨论~

相关推荐
余衫马3 小时前
Windows 10 环境下 Redis 编译与运行指南
redis·后端
青柠编程5 小时前
基于Spring Boot的竞赛管理系统架构设计
java·spring boot·后端
s9123601017 小时前
【rust】 pub(crate) 的用法
开发语言·后端·rust
夕颜1118 小时前
关于排查问题的总结
后端
码事漫谈8 小时前
揭秘RAG的核心引擎:Document、Embedding与Retriever详解
后端
码事漫谈9 小时前
BM25 检索是什么
后端
Moment9 小时前
写代码也能享受?这款显示器让调试变得轻松又高效!😎😎😎
前端·后端
无双_Joney10 小时前
[更新迭代 - 1] Nestjs 在24年底更新了啥?(bug修复篇)
前端·后端·node.js
stark张宇11 小时前
从入门到放弃?一份让PHP学习持续正反馈的知识清单
后端·php
sunbin11 小时前
软件授权管理系统-整体业务流程图(优化版)
后端