本文基于 SSM 架构(Spring+SpringMVC+MyBatis),详细讲解 MyBatis 逆向工程(MBG)的配置、执行、Spring 整合及公共代码抽取,附完整代码和常见问题解决方案,适用于新手快速上手,可直接复制到项目中使用。

一、逆向工程核心作用

       MyBatis 逆向工程(MyBatis Generator,简称 MBG)是 MyBatis 官方提供的代码生成工具,核心价值是解放重复劳动,具体作用如下:

  1. 自动根据数据库表结构生成「实体类(Model)+ Mapper 接口(Dao)+ Mapper 映射文件(XML)」
  2. 生成代码遵循 MyBatis 规范,支持 Spring 无缝整合,可直接通过@Autowired注入使用
  3. 支持灵活扩展,手动新增的自定义方法不会被覆盖
  4. 适配多表场景,可批量生成,搭配公共代码抽取可大幅提升开发效率

二、前置准备(必做)

2.1 项目环境 & 依赖

本文基于 Maven 项目(ham-core 模块),需在pom.xml中添加以下依赖(版本适配稳定,直接复制即可):

<!-- MyBatis逆向工程核心依赖 -->
<dependency>
    <groupId>org.mybatis.generator</groupId>
    <artifactId>mybatis-generator-core</artifactId>
    <version>1.3.7</version>
</dependency>
<!-- MyBatis核心依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>
<!-- Spring整合MyBatis依赖 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.7</version>
</dependency>
<!-- MySQL驱动(MySQL5/8通用,根据版本调整驱动类) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>5.1.47</version>
    <scope>runtime</scope>
</dependency>
<!-- Druid连接池(性能更优,替代默认连接池) -->
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>druid</artifactId>
    <version>1.2.15</version>
</dependency>
<!-- Spring核心依赖(上下文+JDBC+事务) -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.23</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.23</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.23</version>
</dependency>
<!-- 测试依赖(Spring+JUnit4整合) -->
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.13.2</version>
    <scope>test</scope>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.3.23</version>
    <scope>test</scope>
</dependency>

2.2 项目目录结构(规范版)

务必保证目录结构如下(否则会导致配置路径错误、代码生成失败):

ham-core/
├── src/
│   ├── main/
│   │   ├── java/          # 主代码目录(包名按实际项目调整)
│   │   │   └── cn/
│   │   │       └── tx/
│   │   │           ├── model/  # 逆向工程生成:实体类(Songer、Album)
│   │   │           ├── dao/    # 逆向工程生成:Mapper接口(SongerMapper)
│   │   │           ├── service/ # 手动创建:Service接口+实现类
│   │   │           │   └── impl/
│   │   │           └── generator/ # 手动创建:逆向工程执行类
│   │   └── resources/     # 资源配置目录(核心)
│   │       ├── mapper/    # 逆向工程生成:Mapper映射文件(SongerMapper.xml)
│   │       ├── log4j.properties  # 日志配置(可选,打印SQL日志)
│   │       ├── db.properties    # 数据库连接配置(必做)
│   │       ├── generatorConfig.xml  # 逆向工程核心配置(必做)
│   │       ├── sqlMapConfig.xml     # MyBatis全局配置(必做)
│   │       └── beans.xml           # Spring核心配置(必做)
│   └── test/              # 测试目录(与main同级,必做)
│       └── java/
│           └── cn/
│               └── tx/
│                   └── test/      # 测试类(SongerTest、AlbumTest)
└── pom.xml                # 依赖配置文件

三、逆向工程核心配置(generatorConfig.xml)

       这是最关键的一步,所有生成规则都在这里配置,文件放在src/main/resources下,完整配置 + 详细注释如下(直接复制,修改 3 处即可用):

<?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>
    <!-- 上下文配置(核心,唯一标识一个生成规则) -->
    <context id="mybatisGenerator" targetRuntime="MyBatis3">
        <!-- 1. 注释生成器:控制是否生成注释(推荐关闭,简化代码) -->
        <commentGenerator>
            <property name="suppressAllComments" value="true" /> <!-- true:去除所有注释 -->
            <property name="suppressDate" value="true" /> <!-- 去除生成日期注释 -->
        </commentGenerator>

        <!-- 2. 数据库连接配置(【必须修改】3处:URL、用户名、密码) -->
        <jdbcConnection 
            driverClass="com.mysql.jdbc.Driver"  <!-- 注意:MySQL8用com.mysql.cj.jdbc.Driver -->
            connectionURL="jdbc:mysql://localhost:3306/ham?serverTimezone=CTT&amp;useUnicode=true&amp;characterEncoding=utf-8&amp;allowMultiQueries=true" 
            userId="root"  <!-- 你的数据库用户名 -->
            password="root"> <!-- 你的数据库密码 -->
        </jdbcConnection>

        <!-- 3. Java类型解析器:JDBC类型→Java类型映射(无需修改) -->
        <javaTypeResolver>
            <!-- false:JDBC DECIMAL/NUMERIC → Integer;true:→ BigDecimal(按业务选) -->
            <property name="forceBigDecimals" value="false" />
        </javaTypeResolver>

        <!-- 4. 实体类(Model)生成配置(【按需修改】生成路径) -->
        <javaModelGenerator 
            targetPackage="cn.tx.model"  <!-- 实体类存放的包名 -->
            targetProject=".\ham-core\src\main\java"> <!-- 存放目录(相对路径/绝对路径均可) -->
            <property name="enableSubPackages" value="false" /> <!-- 是否按数据库schema分包(false=不分包) -->
            <property name="trimStrings" value="true" /> <!-- 去除字段值前后空格(推荐true) -->
        </javaModelGenerator>

        <!-- 5. Mapper映射文件(XML)生成配置(【按需修改】) -->
        <sqlMapGenerator 
            targetPackage="mapper"  <!-- XML文件存放的包名(resources下) -->
            targetProject=".\ham-core\src\main\resources">
            <property name="enableSubPackages" value="false" />
        </sqlMapGenerator>

        <!-- 6. Mapper接口(Dao)生成配置(【按需修改】) -->
        <javaClientGenerator 
            type="XMLMAPPER"  <!-- 生成方式:XMLMAPPER(接口+XML分离,推荐) -->
            targetPackage="cn.tx.dao"  <!-- Mapper接口存放的包名 -->
            targetProject=".\ham-core\src\main\java">
            <property name="enableSubPackages" value="false" />
        </javaClientGenerator>

        <!-- 7. 指定要生成的数据库表(【必须修改】核心!) -->
        <!-- tableName:数据库表名(支持通配符,如t_*=所有t_开头的表) -->
        <!-- domainObjectName:实体类名(默认驼峰,可自定义,如songer→Songer) -->
        <!-- enable*ByExample:关闭复杂查询(Example),只生成基础CRUD(推荐false) -->
        <table 
            tableName="songer"  <!-- 要生成的数据库表名 -->
            domainObjectName="Songer"  <!-- 对应实体类名 -->
            enableCountByExample="false"
            enableUpdateByExample="false"
            enableDeleteByExample="false"
            enableSelectByExample="false"
            selectByExampleQueryId="false"/>

        <!-- 如需生成多张表,复制上面的<table>标签修改即可 -->
        <!-- <table tableName="album" domainObjectName="Album" .../> -->
    </context>
</generatorConfiguration>

关键配置注意事项(避坑重点)

  1. 数据库连接 URL(高频坑):
    • MySQL8 必须添加 serverTimezone=CTT(中国时区),否则会报时区错误
    • XML 中&需转义为&amp;,否则配置文件解析失败
    • 中文乱码解决:强制添加 useUnicode=true&characterEncoding=utf-8
  2. targetProject 路径(高频坑):
    • 相对路径:以「项目根目录」为基准,如./ham-core/src/main/java(前面的./不能少)
    • 绝对路径(推荐,避免路径错误):如D:/workspace/ham-core/src/main/java
  3. table 标签配置:
    • 若数据库表名带下划线(如song_id),生成的实体类属性会自动转为驼峰(songId
    • 若想生成「带备注的实体类」,关闭suppressAllComments,并添加addRemarkComments=true

四、逆向工程执行(两种方式,推荐方式 1)

       配置完成后,执行生成代码,两种方式任选,优先选「Java 代码执行」(灵活可控,新手易排查错误)

方式 1:Java 代码执行(推荐)

  1. 创建执行类:cn.tx.generator.Generator(包路径按自己的目录调整)
  2. 复制以下代码,仅需修改 1 处:配置文件路径
package cn.tx.generator;

import org.mybatis.generator.api.MyBatisGenerator;
import org.mybatis.generator.config.Configuration;
import org.mybatis.generator.config.xml.ConfigurationParser;
import org.mybatis.generator.internal.DefaultShellCallback;

import java.io.File;
import java.util.ArrayList;
import java.util.List;

/**
 * MyBatis逆向工程执行类(直接运行main方法即可生成代码)
 */
public class Generator {
    public static void main(String[] args) throws Exception {
        // 1. 存储生成过程中的警告信息
        List<String> warnings = new ArrayList<>();
        // 2. 是否覆盖已存在的代码(true=覆盖,false=不覆盖,新手推荐true)
        boolean overwrite = true;
        
        // 3. 【必须修改】逆向工程配置文件路径(与generatorConfig.xml路径一致)
        File configFile = new File("ham-core/src/main/resources/generatorConfig.xml");
        
        // 4. 解析配置文件并执行生成
        ConfigurationParser parser = new ConfigurationParser(warnings);
        Configuration config = parser.parseConfiguration(configFile);
        DefaultShellCallback callback = new DefaultShellCallback(overwrite);
        MyBatisGenerator myBatisGenerator = new MyBatisGenerator(config, callback, warnings);
        myBatisGenerator.generate(null);
        
        // 5. 输出警告信息(若有错误,在这里查看)
        for (String warning : warnings) {
            System.out.println(warning);
        }
        
        System.out.println("✅ 逆向工程执行完成!请查看model、dao、mapper目录");
    }
}

    3.执行步骤:

  • 右键运行main方法
  • 无报错即生成成功,查看对应目录(model、dao、mapper)是否有生成的文件

方式 2:Maven 插件执行(便捷,无需写执行类)

  1. pom.xmlbuild标签中添加 MBG 插件:
<build>
    <plugins>
        <!-- MyBatis逆向工程Maven插件 -->
        <plugin>
            <groupId>org.mybatis.generator</groupId>
            <artifactId>mybatis-generator-maven-plugin</artifactId>
            <version>1.3.7</version>
            <dependencies>
                <!-- 插件需单独引入数据库驱动(必加) -->
                <dependency>
                    <groupId>mysql</groupId>
                    <artifactId>mysql-connector-java</artifactId>
                    <version>5.1.47</version>
                </dependency>
            </dependencies>
            <configuration>
                <!-- 配置文件路径(与generatorConfig.xml一致) -->
                <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                <overwrite>true</overwrite> <!-- 覆盖已存在文件 -->
                <verbose>true</verbose> <!-- 输出执行日志 -->
            </configuration>
        </plugin>
    </plugins>
</build>

    2.执行步骤:

  • IDEA 中:打开 Maven 面板 → Plugins → mybatis-generator → 双击mybatis-generator:generate
  • 命令行:进入项目根目录,执行 mvn mybatis-generator:generate

执行成功验证(必做)

生成后会自动创建 3 类文件,缺一不可:

  1. 实体类:cn.tx.model.Songer.java(含字段、getter/setter、toString)
  2. Mapper 接口:cn.tx.dao.SongerMapper.java(含 insert、selectByPrimaryKey 等基础 CRUD 方法)
  3. Mapper 映射文件:src/main/resources/mapper/SongerMapper.xml(含对应 SQL 语句)

五、Spring 整合 MyBatis(核心,让代码可运行)

       逆向工程生成的是「数据层(Dao)」,需整合 Spring 才能注入使用,核心配置在beans.xmlsqlMapConfig.xml中,步骤如下:

5.1 数据库配置文件(db.properties)

集中管理数据库连接信息,放在resources下,避免硬编码:

# MySQL5配置(直接复制)
driverClass=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/ham?serverTimezone=CTT&useUnicode=true&characterEncoding=utf-8&allowMultiQueries=true
uname=root
pword=root

# MySQL8配置(需使用时,注释上面4行,打开下面4行)
# driverClass=com.mysql.cj.jdbc.Driver
# url=jdbc:mysql://localhost:3306/ham?serverTimezone=CTT&useSSL=false&useUnicode=true&characterEncoding=utf-8
# uname=root
# pword=root

5.2 Spring 核心配置(beans.xml)

       放在resources下,整合数据源、SqlSessionFactory、Mapper 扫描、事务,完整配置如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:context="http://www.springframework.org/schema/context"
       xmlns:aop="http://www.springframework.org/schema/aop"
       xmlns:tx="http://www.springframework.org/schema/tx"
       xsi:schemaLocation="
           http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx.xsd">

    <!-- 1. 扫描注解(Service、Component等,包名按自己的调整) -->
    <context:component-scan base-package="cn.tx"/>

    <!-- 2. 加载数据库配置文件(db.properties) -->
    <context:property-placeholder location="classpath:db.properties"/>

    <!-- 3. 配置Druid数据源(核心,替代默认连接池) -->
    <bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${driverClass}"/>
        <property name="url" value="${url}"/>
        <property name="username" value="${uname}"/>
        <property name="password" value="${pword}"/>
    </bean>

    <!-- 4. 配置SqlSessionFactory(MyBatis核心,关联数据源和MyBatis全局配置) -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource"/> <!-- 关联数据源 -->
        <property name="configLocation" value="classpath:sqlMapConfig.xml"/> <!-- 关联MyBatis全局配置 -->
    </bean>

    <!-- 5. Mapper接口扫描(【关键】自动生成Mapper实现类,注入Spring) -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> <!-- 关联SqlSessionFactory -->
        <property name="basePackage" value="cn.tx.dao"/> <!-- Mapper接口所在包(递归扫描) -->
    </bean>

    <!-- 6. 事务配置(可选,Service层增删改需事务,推荐配置) -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    <!-- 事务通知:配置哪些方法需要事务 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED"/> <!-- 新增方法:必须有事务 -->
            <tx:method name="update*" propagation="REQUIRED"/> <!-- 更新方法 -->
            <tx:method name="del*" propagation="REQUIRED"/> <!-- 删除方法 -->
            <tx:method name="select*" read-only="true"/> <!-- 查询方法:只读事务(优化性能) -->
            <tx:method name="get*" read-only="true"/>
        </tx:attributes>
    </tx:advice>
    <!-- AOP配置:事务作用于Service层 -->
    <aop:config>
        <aop:advisor advice-ref="txAdvice" pointcut="execution(* cn.tx.service..*.*(..))"/>
    </aop:config>
</beans>

5.3 MyBatis 全局配置(sqlMapConfig.xml)

       放在resources下,主要作用是注册 Mapper 映射文件,简化配置:

<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">
<configuration>
    <!-- 可选:开启驼峰命名自动转换(数据库字段名_abc → Java属性名abc) -->
    <settings>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
        <setting name="logImpl" value="STDOUT_LOGGING"/> <!-- 打印SQL日志(调试用) -->
    </settings>
    
    <!-- 注册Mapper映射文件(两种方式,选一种即可) -->
    <mappers>
        <!-- 方式1:单个注册(适合少量表) -->
        <mapper resource="mapper/SongerMapper.xml"/>
        <!-- <mapper resource="mapper/AlbumMapper.xml"/> -->
        
        <!-- 方式2:批量注册(推荐,扫描mapper目录下所有XML) -->
        <!-- <package name="mapper"/> -->
    </mappers>
</configuration>

六、Service 层封装(基于生成的 Mapper)

       逆向工程生成的是数据层(Dao),需手动封装 Service 层(业务逻辑层),实现 CRUD 业务,代码如下(以 Songer 为例):

6.1 Service 接口(cn.tx.service.SongerService)

package cn.tx.service;

import cn.tx.model.Songer;
import java.util.List;

/**
 * Songer业务接口(基础CRUD+按需扩展)
 */
public interface SongerService {
    // 新增歌手
    void addSonger(Songer songer);
    
    // 根据主键查询歌手
    Songer getSongerById(Integer id);
    
    // 选择性更新歌手(只更新非null字段,推荐)
    void updateSonger(Songer songer);
    
    // 根据主键删除歌手
    void delSongerById(Integer id);
    
    // 查询所有歌手(需手动扩展Mapper方法)
    List<Songer> getAllSonger();
}

6.2 Service 实现类(cn.tx.service.impl.SongerServiceImpl)

package cn.tx.service.impl;

import cn.tx.dao.SongerMapper;
import cn.tx.model.Songer;
import cn.tx.service.SongerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;

/**
 * Songer业务实现类(注入Mapper,调用数据层方法)
 */
@Service // 交给Spring管理,允许@Autowired注入
public class SongerServiceImpl implements SongerService {

    // 注入逆向工程生成的Mapper接口(Spring自动生成实现类,无需手动写)
    @Autowired
    private SongerMapper songerMapper;

    @Override
    public void addSonger(Songer songer) {
        songerMapper.insert(songer); // 调用逆向工程生成的insert方法
    }

    @Override
    public Songer getSongerById(Integer id) {
        return songerMapper.selectByPrimaryKey(id); // 调用生成的查询方法
    }

    @Override
    public void updateSonger(Songer songer) {
        songerMapper.updateByPrimaryKeySelective(songer); // 选择性更新
    }

    @Override
    public void delSongerById(Integer id) {
        songerMapper.deleteByPrimaryKey(id); // 调用生成的删除方法
    }

    @Override
    public List<Songer> getAllSonger() {
        // 若逆向工程未生成selectAll方法,需手动在SongerMapper接口+XML中扩展
        return songerMapper.selectObjectAll();
    }
}

七、测试验证(SpringJUnit,必做,避免踩坑)

       通过 JUnit 测试整合结果,确保 Dao、Service、Spring 能正常联动,测试类放在src/test/java/cn/tx/test下:

package cn.tx.test;

import cn.tx.model.Songer;
import cn.tx.service.SongerService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

/**
 * Songer业务测试类(Spring+JUnit4整合)
 */
// 固定注解:整合Spring和JUnit4
@RunWith(SpringJUnit4ClassRunner.class)
// 加载Spring配置文件(beans.xml路径)
@ContextConfiguration(locations = "classpath:beans.xml")
public class SongerTest {

    // 注入Service(测试Service层,间接测试Dao层)
    @Autowired
    private SongerService songerService;

    // 测试新增(先执行此方法)
    @Test
    public void testAdd() {
        Songer songer = new Songer();
        songer.setArea("北京");
        songer.setIntro("测试歌手");
        songer.setIsHot(1);
        songer.setPic("test.jpg");
        songer.setSrname("测试名称");
        songerService.addSonger(songer);
        System.out.println("✅ 新增歌手成功!");
    }

    // 测试查询(新增成功后执行)
    @Test
    public void testGetById() {
        Songer songer = songerService.getSongerById(1); // 主键id按实际新增的调整
        System.out.println("✅ 查询结果:" + songer);
    }

    // 测试更新(查询成功后执行)
    @Test
    public void testUpdate() {
        Songer songer = songerService.getSongerById(1);
        songer.setSrname("更新后的歌手名称");
        songerService.updateSonger(songer);
        System.out.println("✅ 更新歌手成功!");
    }

    // 测试删除(最后执行)
    @Test
    public void testDelete() {
        songerService.delSongerById(1);
        System.out.println("✅ 删除歌手成功!");
    }
}

测试注意事项(避坑)

  1. 测试前必须启动 MySQL 服务,且ham数据库、songer表已创建(字段与实体类一致)
  2. 测试方法执行顺序:testAdd → testGetById → testUpdate → testDelete
  3. 若出现「Mapper 注入失败」:检查beans.xmlMapperScannerConfigurerbasePackage是否为cn.tx.dao
  4. 若出现「SQL 执行失败」:打开sqlMapConfig.xml的 SQL 日志,查看打印的 SQL,核对表名、字段名是否正确

八、公共代码抽取(优化扩展,多表场景必用)

       当项目中有多个实体类(如 Songer、Album、User)时,每个实体类都要写 Dao、Service,会有大量重复代码,此时抽取「公共 BaseDao、BaseService」,简化开发:

8.1 公共 BaseDao 接口(cn.tx.dao.BaseDao)

       所有 Mapper 接口继承此类,无需重复声明基础 CRUD 方法:

package cn.tx.dao;

import java.util.List;

/**
 * 公共Dao接口(所有Mapper接口的父接口)
 * @param <T> 实体类泛型(适配不同实体类)
 */
public interface BaseDao<T> {
    // 基础CRUD方法(与逆向工程生成的方法一致)
    void insert(T t);
    T selectByPrimaryKey(Integer id);
    void deleteByPrimaryKey(Integer id);
    void updateByPrimaryKeySelective(T t);
    List<T> selectObjectAll(); // 自定义查询所有(需在XML中手动实现)
}

8.2 Mapper 接口简化(继承 BaseDao)

package cn.tx.dao;

import cn.tx.model.Songer;

// 继承BaseDao,无需重复写CRUD方法(直接复用)
public interface SongerMapper extends BaseDao<Songer> {
    // 按需扩展自定义方法(如复杂查询)
}

8.3 公共 BaseService 接口(cn.tx.service.BaseService)

package cn.tx.service;

import java.util.List;

/**
 * 公共Service接口(所有Service接口的父接口)
 * @param <T> 实体类泛型
 */
public interface BaseService<T> {
    void insert(T t);
    T selectByPrimaryKey(Integer id);
    void deleteByPrimaryKey(Integer id);
    void updateByPrimaryKeySelective(T t);
    List<T> selectObjectAll();
}

8.4 公共 BaseService 实现类(cn.tx.service.impl.BaseServiceImpl)

package cn.tx.service.impl;

import cn.tx.dao.BaseDao;
import cn.tx.service.BaseService;
import java.util.List;

/**
 * 公共Service实现类(抽象类,所有Service实现类继承)
 * @param <T> 实体类泛型
 */
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    // 由子类注入具体的Mapper(父类定义,子类赋值)
    protected BaseDao<T> baseDao;

    // 抽象方法:子类必须实现,注入具体的Mapper
    public abstract void setBaseDao(BaseDao<T> baseDao);

    // 复用基础CRUD方法(无需子类重复写)
    @Override
    public void insert(T t) {
        baseDao.insert(t);
    }

    @Override
    public T selectByPrimaryKey(Integer id) {
        return baseDao.selectByPrimaryKey(id);
    }

    @Override
    public void deleteByPrimaryKey(Integer id) {
        baseDao.deleteByPrimaryKey(id);
    }

    @Override
    public void updateByPrimaryKeySelective(T t) {
        baseDao.updateByPrimaryKeySelective(t);
    }

    @Override
    public List<T> selectObjectAll() {
        return baseDao.selectObjectAll();
    }
}

8.5 子类 Service 实现类简化(以 Album 为例)

package cn.tx.service.impl;

import cn.tx.dao.AlbumMapper;
import cn.tx.dao.BaseDao;
import cn.tx.model.Album;
import cn.tx.service.AlbumService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

/**
 * Album业务实现类(继承公共BaseServiceImpl,简化代码)
 */
@Service
public class AlbumServiceImpl extends BaseServiceImpl<Album> implements AlbumService {

    // 注入具体的Mapper(AlbumMapper)
    @Autowired
    private AlbumMapper albumMapper;

    // 实现父类抽象方法,注入baseDao
    @Override
    public void setBaseDao(BaseDao<Album> baseDao) {
        this.baseDao = baseDao;
    }

    // 注入AlbumMapper,给baseDao赋值
    @Autowired
    public void setAlbumMapper(AlbumMapper albumMapper) {
        this.albumMapper = albumMapper;
        this.baseDao = albumMapper;
    }
}

九、常见问题与解决方案(高频坑,必看)

问题描述核心原因解决方案
逆向工程执行失败,提示「配置文件找不到」generatorConfig.xml 路径错误1. 改用绝对路径(如 D:/xxx/generatorConfig.xml);2. 相对路径以项目根目录为基准,核对层级
生成的实体类字段与数据库表字段不一致未开启驼峰命名转换在 sqlMapConfig.xml 中添加<setting name="mapUnderscoreToCamelCase" value="true"/>
Mapper 接口注入失败(@Autowired 报红)1. 未配置 MapperScannerConfigurer;2. basePackage 错误1. 检查 beans.xml 中是否配置 MapperScannerConfigurer;2. 确认 basePackage 是 Mapper 接口所在包(cn.tx.dao)
测试时提示「数据库连接失败」1. 数据库未启动;2. 连接信息错误;3. 驱动版本不匹配1. 启动 MySQL 服务;2. 核对 db.properties 的用户名、密码、数据库名;3. MySQL8 用 8.x 驱动,MySQL5 用 5.x 驱动
逆向工程生成的 XML 中 SQL 报错数据库字段类型与 Java 类型映射错误在 generatorConfig.xml 的<table>标签中添加<columnOverride column="字段名" javaType="Java类型"/>
执行新增方法后,数据库无数据未配置事务,新增方法抛异常未回滚1. 配置 beans.xml 中的事务;2. 检查实体类字段是否与表字段一致(如主键是否自增)

十、实用技巧(提升开发效率)

  1. 批量生成多张表:在 generatorConfig.xml 中添加多个<table>标签,或用通配符tableName="t_*"(生成所有 t_开头的表)
  2. 保留手动修改的代码:将执行类中的overwrite改为false,逆向工程只会生成「新增表」的代码,不会覆盖已修改的代码
  3. 生成带备注的实体类:关闭suppressAllComments,添加<property name="addRemarkComments" value="true"/>,实体类会显示数据库字段备注
  4. 调试 SQL:在 sqlMapConfig.xml 中开启STDOUT_LOGGING,打印执行的 SQL、参数、返回值,快速排查 SQL 错误
  5. 多环境适配:将 db.properties 按环境拆分(db-dev.properties、db-test.properties),在 beans.xml 中通过profile切换环境

总结

       MyBatis 逆向工程是 SSM 项目的「效率神器」,核心流程可概括为:配置generatorConfig.xml → 执行逆向工程生成代码 → Spring整合MyBatis → 封装Service层 → 测试验证 → 公共代码抽取优化

       本文所有代码均经过实测,可直接复制到项目中使用,新手只需修改「数据库连接信息、生成路径、数据库表名」3 处,即可快速上手。多表场景下,通过公共 BaseDao、BaseService 抽取,可大幅减少重复代码,提升项目可维护性。

       如果觉得本文有用,欢迎点赞 + 收藏,后续会持续更新 SSM 项目实战技巧~

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐