Spring 整合 MyBatis 全流程详解(附 Junit 单元测试实战)(Spring系列6)

摘要:Spring作为Java后端的核心框架,提供了强大的IoC容器来管理Bean;MyBatis是优秀的持久层框架,简化了JDBC的繁琐操作。本文从纯MyBatis开发流程入手,深入分析Spring整合MyBatis的核心思路,一步步带你完成环境搭建、配置编写、代码实现,同时补充Spring整合Junit单元测试的完整方案,附完整代码、项目结构、对比分析,帮你彻底掌握Spring整合MyBatis的原理与实践。

一、纯MyBatis开发流程回顾(环境准备)

在整合Spring之前,我们先回顾纯MyBatis的开发流程,明确MyBatis的核心对象和配置,为后续整合做铺垫。

1.1 环境搭建步骤

步骤1:准备数据库表

MyBatis用于操作数据库,首先创建数据库和表:

create database spring_db character set utf8; use spring_db; create table tbl_account( id int primary key auto_increment, name varchar(35), money double );

步骤2:创建项目导入Jar包(pom.xml)

<dependencies> <!-- Spring核心依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-context</artifactId> <version>5.2.10.RELEASE</version> </dependency> <!-- Druid连接池 --> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.1.16</version> </dependency> <!-- MyBatis核心依赖 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis</artifactId> <version>3.5.6</version> </dependency> <!-- MySQL驱动 --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.47</version> </dependency> </dependencies>

步骤3:创建模型类(domain包)

public class Account implements Serializable { private Integer id; private String name; private Double money; // 构造器、getter、setter、toString方法略 }

步骤4:创建Dao接口

public interface AccountDao { @Insert("insert into tbl_account(name,money)values(#{name},#{money})") void save(Account account); @Delete("delete from tbl_account where id = #{id} ") void delete(Integer id); @Update("update tbl_account set name = #{name} , money = #{money} where id = #{id} ") void update(Account account); @Select("select * from tbl_account") List<Account> findAll(); @Select("select * from tbl_account where id = #{id} ") Account findById(Integer id); }

步骤5:创建Service接口和实现类

// Service接口 public interface AccountService { void save(Account account); void delete(Integer id); void update(Account account); List<Account> findAll(); Account findById(Integer id); } // Service实现类 @Service public class AccountServiceImpl implements AccountService { @Autowired private AccountDao accountDao; @Override public void save(Account account) { accountDao.save(account); } @Override public void update(Account account){ accountDao.update(account); } @Override public void delete(Integer id) { accountDao.delete(id); } @Override public Account findById(Integer id) { return accountDao.findById(id); } @Override public List<Account> findAll() { return accountDao.findAll(); } }

步骤6:添加jdbc.properties配置文件

jdbc.driver=com.mysql.jdbc.Driver jdbc.url=jdbc:mysql://localhost:3306/spring_db?useSSL=false jdbc.username=root jdbc.password=root

说明:useSSL=false用于关闭MySQL的SSL连接,避免警告。

步骤7:添加MyBatis核心配置文件SqlMapConfig.xml

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE configuration PUBLIC "-//mybatis.org//DTD Config 3.0//EN" "http://mybatis.org/dtd/mybatis-3.dtd"> <configuration> <!-- 读取外部properties配置文件 --> <properties resource="jdbc.properties"></properties> <!-- 别名扫描的包路径 --> <typeAliases> <package name="com.itheima.domain"/> </typeAliases> <!-- 数据源 --> <environments default="mysql"> <environment> <transactionManager type="JDBC"></transactionManager> <dataSource type="POOLED"> <property name="driver" value="${jdbc.driver}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </dataSource> </environment> </environments> <!-- 映射文件扫描包路径 --> <mappers> <package name="com.itheima.dao"/> </mappers> </configuration>

步骤8:编写应用程序

public class App { public static void main(String[] args) throws IOException { // 1. 创建SqlSessionFactoryBuilder对象 SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder(); // 2. 加载SqlMapConfig.xml配置文件 InputStream inputStream = Resources.getResourceAsStream("SqlMapConfig.xml"); // 3. 创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = sqlSessionFactoryBuilder.build(inputStream); // 4. 获取SqlSession SqlSession sqlSession = sqlSessionFactory.openSession(); // 5. 执行SqlSession对象执行查询,获取结果 AccountDao accountDao = sqlSession.getMapper(AccountDao.class); Account ac = accountDao.findById(1); System.out.println(ac); // 6. 释放资源 sqlSession.close(); } }

步骤9:运行程序

Account{id=1, name='Tom', money=1000.0} Process finished with exit code 0

1.2 MyBatis核心对象与整合思路分析

1.2.1 MyBatis核心对象分析

对象作用是否需要Spring管理
SqlSessionFactoryBuilder构建SqlSessionFactory无需,用完即弃
SqlSessionFactoryMyBatis核心工厂,创建SqlSession✅ 单例,需要交给Spring管理
SqlSession会话,相当于数据库连接,获取Mapper❌ 线程不安全,每次手动获取
Mapper接口(AccountDao)数据层操作接口✅ 需要Spring扫描生成代理对象

1.2.2 整合核心思路

Spring整合MyBatis的核心就是两件事

  1. Spring管理SqlSessionFactory:将MyBatis的核心工厂交给Spring IoC容器,统一管理,避免手动创建。
  2. Spring管理Mapper接口的扫描:自动扫描Dao接口,生成代理对象,交给Spring容器,直接@Autowired注入使用。

同时,原来MyBatis配置文件SqlMapConfig.xml中的所有配置,都可以通过Spring的配置类来实现,最终可以完全舍弃该配置文件。


二、Spring整合MyBatis完整步骤

2.1 导入整合依赖

<!-- Spring操作数据库依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>5.2.10.RELEASE</version> </dependency> <!-- MyBatis提供的Spring整合包 --> <dependency> <groupId>org.mybatis</groupId> <artifactId>mybatis-spring</artifactId> <version>1.3.0</version> </dependency>

说明:mybatis-spring是MyBatis官方提供的Spring整合工具包,封装了SqlSessionFactoryBean、MapperScannerConfigurer等核心类。

2.2 创建Spring主配置类

@Configuration @ComponentScan("com.itheima") @PropertySource("classpath:jdbc.properties") public class SpringConfig { }
  • @Configuration:标记该类为Spring配置类
  • @ComponentScan:组件扫描,扫描项目中的Service、Dao等Bean
  • @PropertySource:加载jdbc.properties配置文件

2.3 数据源配置类(Druid连接池)

public class JdbcConfig { @Value("${jdbc.driver}") private String driver; @Value("${jdbc.url}") private String url; @Value("${jdbc.username}") private String userName; @Value("${jdbc.password}") private String password; @Bean public DataSource dataSource(){ DruidDataSource ds = new DruidDataSource(); ds.setDriverClassName(driver); ds.setUrl(url); ds.setUsername(userName); ds.setPassword(password); return ds; } }

2.4 MyBatis核心配置类

public class MybatisConfig { /** * 配置SqlSessionFactoryBean,生成SqlSessionFactory */ @Bean public SqlSessionFactoryBean sqlSessionFactoryBean(DataSource dataSource){ SqlSessionFactoryBean ssfb = new SqlSessionFactoryBean(); // 设置模型类的别名扫描包 ssfb.setTypeAliasesPackage("com.itheima.domain"); // 设置数据源(自动注入Spring管理的DruidDataSource) ssfb.setDataSource(dataSource); return ssfb; } /** * 配置MapperScannerConfigurer,扫描Dao接口生成代理对象 */ @Bean public MapperScannerConfigurer mapperScannerConfigurer(){ MapperScannerConfigurer msc = new MapperScannerConfigurer(); // 设置Dao接口的扫描包路径 msc.setBasePackage("com.itheima.dao"); return msc; } }

重点说明:配置了MapperScannerConfigurer批量扫描dao包后,Mapper接口上无需添加@Mapper注解,即可被Spring管理并支持@Autowired注入。

1. @Mapper 注解

MyBatis 提供的注解,作用是标记当前接口为 Mapper 接口,让 Spring 能为该接口生成代理对象并注入到容器中。

2. @MapperScan / MapperScannerConfigurer

作用是批量扫描指定包下的所有接口,自动将其识别为 Mapper 接口,统一生成代理对象,无需逐个接口加注解。

3. 两者的使用关系

只要配置了批量扫描(@MapperScan / MapperScannerConfigurer),接口上就不需要再写 @Mapper;即使写了也不会报错,但属于冗余配置,没有实际作用。

4. 不同开发场景的使用规范
  • 传统 SSM 框架:使用 MapperScannerConfigurer 配置批量扫描,接口上不写 @Mapper
  • Spring Boot(主流方案):在启动类上添加 @MapperScan("xxx.dao") 配置扫描包,接口上不写 @Mapper
  • 唯一必须写 @Mapper 的场景:没有任何批量扫描配置,仅单独使用某个 Mapper 接口,这句话仅在 Spring Boot 中是可实现的。在 SSM 中不成立,因为 SSM 中即使给单个接口加 @Mapper,不配置扫描器也无法生效,不存在「不配置批量扫描就能单独用 @Mapper」的情况。
补充生效规则:
  • 纯 Spring(SSM)环境:@Mapper 必须配合 MapperScannerConfigurer 才能生效;
  • Spring Boot 环境:@Mapper 可以直接生效,因为 Spring Boot 的 MyBatis 自动配置已经帮你完成了底层扫描逻辑。

2.5 完善主配置类

@Configuration @ComponentScan("com.itheima") @PropertySource("classpath:jdbc.properties") @Import({JdbcConfig.class, MybatisConfig.class}) public class SpringConfig { }

2.6 编写运行测试类

public class App2 { public static void main(String[] args) { // 启动Spring容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取Service Bean AccountService accountService = ctx.getBean(AccountService.class); // 执行查询 Account ac = accountService.findById(1); System.out.println(ac); } }

2.7 项目结构说明

spring_15_spring_mybatis ├── src │ ├── main │ │ ├── java │ │ │ └── com.itheima │ │ │ ├── config │ │ │ │ ├── JdbcConfig.java │ │ │ │ ├── MybatisConfig.java │ │ │ │ └── SpringConfig.java │ │ │ ├── dao │ │ │ │ └── AccountDao.java │ │ │ ├── domain │ │ │ │ └── Account.java │ │ │ ├── service │ │ │ │ ├── AccountService.java │ │ │ │ └── impl │ │ │ │ └── AccountServiceImpl.java │ │ │ ├── App.java │ │ │ └── App2.java │ │ └── resources │ │ └── jdbc.properties └── pom.xml

三、Spring整合Junit单元测试

3.1 环境准备

直接使用上面整合好的Spring+MyBatis项目,在test目录下编写测试类。

3.2 整合步骤与代码实现

步骤 1:引入依赖 在pom.xml中添加 Junit 和 Spring 测试依赖:<!-- Junit依赖 --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> <scope>test</scope> </dependency> <!-- Spring测试依赖 --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-test</artifactId> <version>5.2.10.RELEASE</version> </dependency>
步骤 2:编写测试类 在test/java/com/itheima下创建AccountServiceTest测试类:// 设置运行器:Spring整合Junit的专用运行器 @RunWith(SpringJUnit4ClassRunner.class) // 设置Spring配置类 @ContextConfiguration(classes = SpringConfig.class) public class AccountServiceTest { // 自动注入Service Bean @Autowired private AccountService accountService; @Test public void testFindById(){ System.out.println(accountService.findById(1)); } @Test public void testFindAll(){ System.out.println(accountService.findAll()); } }

关键注解说明:
@RunWith(SpringJUnit4ClassRunner.class):必须添加,Spring 提供的专用运行器,负责自动创建 Spring 容器。
@ContextConfiguration(classes = SpringConfig.class):指定 Spring 配置类,加载容器。
@Autowired:直接注入 Bean,无需手动获取。

3.3 整合vs手动方式对比

对比项整合Spring+Junit(推荐)不整合(手动)
容器创建自动创建手动new容器
Bean获取@Autowired直接注入getBean获取
代码简洁性极高冗余

手动方式代码示例(不推荐):

 public class AccountServiceTest { @Test public void testFindById() { // 手动创建Spring容器 ApplicationContext ctx = new AnnotationConfigApplicationContext(SpringConfig.class); // 获取Bean AccountService accountService = ctx.getBean(AccountService.class); // 执行测试 System.out.println(accountService.findById(1)); } }

四、常见问题与注意事项

  1. SqlSessionFactoryBean的dataSource必须是Spring管理的,不能手动new。
  2. MapperScannerConfigurer的basePackage必须准确,否则无法生成Mapper代理对象。
  3. 配置MapperScannerConfigurer后,Mapper接口不需要@Mapper注解。
  4. @PropertySource必须加classpath:,确保配置文件加载成功。
  5. SqlSession线程不安全,不能交给Spring单例管理。
  6. 测试类中@RunWith必须在@ContextConfiguration之前。

五、总结

Spring整合MyBatis的核心思想是将MyBatis的核心对象交给Spring IoC容器统一管理,实现解耦、简化开发、统一配置:

  • 用SqlSessionFactoryBean替代SqlMapConfig.xml,管理SqlSessionFactory;
  • 用MapperScannerConfigurer自动扫描Dao接口,生成代理对象,无需@Mapper
  • 整合Junit后,自动创建容器,大幅简化单元测试。

Read more

AIGC(生成式AI)试用 45 -- DocsGPT 与 Python开发 1

一切从python调用本地DocsGPT完成python开发开始。 遗留问题:如何验证AI开发提交的结果? * 提问 1: 使用python+Tkinter进行GUI程序编码 1. 界面分为左右两部分     - 左侧为python代码编辑区:       左上部为代码多行输入框,嵌入python idle,浅灰色底色;       左下部为 Run 按钮     - 右侧为GPT调用区:       右上部为tab,名称 Question,嵌入多行文本,输入提问问题;       中部为Show Answer按钮,海蓝色;       下部为2个tab:tab1,名称 Answer,嵌入多行文本,显示GPT处理结果;                                tab2,名称History,显示提问历史,answer + question,数据来自名为pyai的sqlite的数据库  2. 优化界面  3. 优化代码 * DeepSeek 回复 1: - 1 次调用界面

2026年AI编程工具全景图:GitHub Copilot vs Cursor vs Codeium,我如何选择?

2026年AI编程工具全景图:GitHub Copilot vs Cursor vs Codeium,我如何选择?

文章目录 * 前言 * 一、我的使用场景与测试环境 * 二、GitHub Copilot:全球生态标杆 * 核心优势实测 * 性能数据记录 * 鸿蒙开发适配度 * 三、Cursor:专家级重构利器 * 重构能力深度测试 * 多文件分析能力 * 四、Codeium:极致免费的性价比之选 * 免费策略的深度体验 * 响应速度实测 * 中文支持的优势 * 五、鸿蒙开发场景专项测试 * 测试1:ArkTS组件生成 * 测试2:分布式能力集成 * 测试3:性能优化建议 * 六、2026年价格策略对比 * 七、我的实际使用组合 * 工作日使用方案 * 具体工作流 * 效率提升数据 * 八、选择建议:根据你的场景决策 * 场景1:学生/初学者/零预算 * 场景2:前端/鸿蒙开发者 * 场景3:全栈/团队协作

2026最火的6款免费AI写作软件测评:ai写网文哪个好用?这款ai消痕工具

2026最火的6款免费AI写作软件测评:ai写网文哪个好用?这款ai消痕工具

很多朋友想在业余时间写写番茄、起点网文或者搞搞短剧赚点外快,但总是卡在“憋不出字”或者“大纲写崩”上。现在都2026年了,用ai写作软件来辅助写小说早就不是秘密了。 但是,网文平台的审核越来越严,很多新手直接用AI生成的文章发出去,立马就被平台判定为“AI生成”导致限流,不仅没流量,连全勤奖都拿不到。 今天,我们就抛开那些晦涩难懂的技术术语,用大白话给大家实测目前市面上热度最高的6款免费ai写作平台。到底ai写网文哪家强?怎么解决让人头疼的“机器味”?这篇超详细的避坑指南,建议想靠文字搞钱的朋友直接收藏! 一、 6大热门免费AI小说工具优缺点大盘点 我们选了大家最常搜的几款工具,直接看它们在实际写小说、写剧本时的真实表现。 1. 豆包:起名和找灵感的“点子王” * 优点:速度飞快,完全免费。你如果卡文了,或者不知道主角叫什么、书名怎么起才能吸引人,直接问豆包,它能一秒钟给你吐出几十个极其符合抖音、小红书调性的网感标题和名字。 * 缺点:千万别让它直接给你写正文!它的AI味太重了,动不动就是“嘴角勾起一抹弧度”、“倒吸一口凉气”。把这种文发到小说平台,

2026 免费 AI 编程助手排行榜:文心快码、Copilot 与 Cursor 深度评测

2026年度核心结论速览 基于 IDC《中国生成式 AI 代码工具评估 2025》 及 Stack Overflow 2026 开发者调查 数据,我们将主流工具分为三个梯队。 * 行业现状:据 McKinsey 报告显示,AI 辅助开发使新手工程师效率提升 2倍,熟练开发者编码速度提升 55%。 * Tier 0 (工程化首选):文心快码 (Comate)。唯一在 IDC 评估中斩获 8项满分 的产品,支持企业级免费开通与个人免费使用,是目前唯一具备完整“代码智能体(Coding Agent)”形态的工具。 * Tier 1 (生态首选):GitHub Copilot。全球生态最强,拥有 85% 的开发者信心提升率,适合开源社区重度用户。 * Tier