尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
MyBatis与Spring整合:注解与XML配置实践指南
1. MyBatis与Spring整合的核心价值作为Java生态中最主流的ORM框架之一MyBatis凭借其灵活的SQL掌控力和简洁的配置方式在企业级应用开发中占据重要地位。而Spring框架的IoC容器和事务管理能力则为MyBatis提供了完美的运行环境。这种组合既保留了直接操作SQL的灵活性又享受到了Spring带来的开发便利。在实际项目中我们通常会面临两种选择通过注解直接在接口方法上编写SQL或者使用XML文件集中管理SQL语句。注解方式的最大优势在于开发效率——SQL与Java代码共存跳转查看非常方便而XML方式则更适合复杂SQL的场景尤其是需要动态拼接的条件查询其清晰的层级结构使得SQL可读性大幅提升。2. 注解方式实现CRUD操作2.1 基础环境搭建首先确保项目中包含必要的依赖。对于Maven项目pom.xml需要添加dependency groupIdorg.mybatis.spring.boot/groupId artifactIdmybatis-spring-boot-starter/artifactId version3.0.3/version /dependency dependency groupIdcom.mysql/groupId artifactIdmysql-connector-j/artifactId scoperuntime/scope /dependencySpring Boot的自动配置会帮我们完成大部分初始化工作包括DataSource的创建和MyBatis组件的注册。我们只需要在application.properties中配置数据库连接信息spring.datasource.urljdbc:mysql://localhost:3306/test_db spring.datasource.usernameroot spring.datasource.password123456 spring.datasource.driver-class-namecom.mysql.cj.jdbc.Driver2.2 核心注解使用详解MyBatis提供了一系列注解来简化开发。最基本的Select、Insert、Update和Delete对应着CRUD操作Mapper public interface UserMapper { Select(SELECT * FROM users WHERE id #{id}) User findById(Param(id) Long id); Insert(INSERT INTO users(name,email) VALUES(#{name},#{email})) Options(useGeneratedKeys true, keyProperty id) int insert(User user); Update(UPDATE users SET name#{name}, email#{email} WHERE id#{id}) int update(User user); Delete(DELETE FROM users WHERE id#{id}) int deleteById(Param(id) Long id); }这里有几个关键点需要注意Mapper注解标记这是一个MyBatis的Mapper接口Spring会为其创建代理实现Param注解明确指定参数名特别是在方法有多个参数时必须使用Options中的useGeneratedKeys配置在插入后自动回填生成的主键2.3 动态SQL的注解实现对于条件查询我们可以使用SelectProvider等注解实现动态SQLSelectProvider(type UserSqlProvider.class, method findByCondition) ListUser findByCondition(Param(name) String name, Param(email) String email); public class UserSqlProvider { public String findByCondition(MapString, Object params) { return new SQL() {{ SELECT(*); FROM(users); if (params.get(name) ! null) { WHERE(name like #{name}); } if (params.get(email) ! null) { WHERE(email #{email}); } }}.toString(); } }这种方式虽然不如XML直观但在需要高度动态化的场景下非常有用。SQL构建器类可以帮助我们避免字符串拼接带来的SQL注入风险。3. XML配置方式详解3.1 XML映射文件基础配置XML方式需要先在application.properties中指定mapper文件位置mybatis.mapper-locationsclasspath:mapper/*.xml然后创建对应的XML文件通常放在resources/mapper目录下。一个完整的UserMapper.xml示例?xml version1.0 encodingUTF-8? !DOCTYPE mapper PUBLIC -//mybatis.org//DTD Mapper 3.0//EN http://mybatis.org/dtd/mybatis-3-mapper.dtd mapper namespacecom.example.mapper.UserMapper resultMap iduserResultMap typecom.example.entity.User id propertyid columnid/ result propertyname columnname/ result propertyemail columnemail/ /resultMap select idfindById resultMapuserResultMap SELECT * FROM users WHERE id #{id} /select !-- 其他CRUD操作 -- /mapper3.2 动态SQL标签实践XML方式最大的优势在于其强大的动态SQL能力。MyBatis提供了一系列标签来处理各种场景select idfindByCondition resultMapuserResultMap SELECT * FROM users where if testname ! null and name ! AND name like CONCAT(%,#{name},%) /if if testemail ! null AND email #{email} /if choose when testorderBy name ORDER BY name /when otherwise ORDER BY id /otherwise /choose /where /select常用的动态SQL标签包括if条件判断choose/when/otherwise多条件选择foreach集合遍历常用于IN查询bind创建变量并绑定到上下文3.3 复杂查询与结果映射对于复杂的关联查询XML方式可以清晰地定义结果映射resultMap iduserWithOrdersMap typeUser id propertyid columnuser_id/ result propertyname columnuser_name/ collection propertyorders ofTypeOrder id propertyid columnorder_id/ result propertyorderNo columnorder_no/ result propertyamount columnamount/ /collection /resultMap select idfindUserWithOrders resultMapuserWithOrdersMap SELECT u.id as user_id, u.name as user_name, o.id as order_id, o.order_no, o.amount FROM users u LEFT JOIN orders o ON u.id o.user_id WHERE u.id #{userId} /select这种一对多的关联映射在XML中可以非常清晰地表达而用注解实现则会显得冗长且难以维护。4. 混合使用注解与XML4.1 策略选择与最佳实践在实际项目中我们通常会根据场景混合使用两种方式。一些经验法则简单的CRUD操作使用注解提高开发效率复杂的动态查询使用XML保持可读性关联查询和结果映射优先使用XML需要高度动态化的SQL可以考虑使用Provider注解4.2 事务管理配置无论使用哪种方式Spring的事务管理都能很好地工作。我们只需要在Service层添加Transactional注解Service public class UserService { Autowired private UserMapper userMapper; Transactional public void updateUser(User user) { userMapper.update(user); // 其他数据库操作 } }MyBatis会与Spring的事务管理器无缝集成确保操作的原子性。5. 常见问题排查与性能优化5.1 典型错误与解决方案参数绑定错误当出现There is no getter for property named xxx in class java.lang.String时检查是否在多参数方法上遗漏了Param注解XML文件未被加载确保application.properties中配置了正确的mybatis.mapper-locations路径且文件后缀为.xmlSQL语法错误复杂的动态SQL建议先在数据库客户端测试再写入XML缓存问题MyBatis有一级缓存和二级缓存当数据被其他方式修改时可能需要手动清除缓存5.2 性能优化建议批量操作使用 标签实现批量插入比单条插入效率高很多insert idbatchInsert INSERT INTO users(name,email) VALUES foreach collectionlist itemuser separator, (#{user.name},#{user.email}) /foreach /insert延迟加载对于关联查询配置懒加载避免不必要的数据查询resultMap iduserWithOrdersLazyMap typeUser collection propertyorders ofTypeOrder selectcom.example.mapper.OrderMapper.findByUserId columnid fetchTypelazy/ /resultMapSQL优化避免在循环中执行SQL尽量通过一次查询获取所需数据6. 高级特性与扩展6.1 插件开发MyBatis的插件机制允许我们在SQL执行的生命周期中插入自定义逻辑。常见的拦截点包括Executor拦截增删改查操作ParameterHandler拦截参数处理ResultSetHandler拦截结果集处理StatementHandler拦截SQL语句构建创建一个简单的SQL执行时间统计插件Intercepts({ Signature(type Executor.class, method update, args {MappedStatement.class, Object.class}), Signature(type Executor.class, method query, args {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}) }) public class SqlCostInterceptor implements Interceptor { Override public Object intercept(Invocation invocation) throws Throwable { long start System.currentTimeMillis(); try { return invocation.proceed(); } finally { long cost System.currentTimeMillis() - start; System.out.println(SQL执行耗时 cost ms); } } Override public Object plugin(Object target) { return Plugin.wrap(target, this); } Override public void setProperties(Properties properties) { } }然后在配置类中注册这个插件Configuration public class MyBatisConfig { Bean public SqlCostInterceptor sqlCostInterceptor() { return new SqlCostInterceptor(); } }6.2 类型处理器自定义类型处理器可以处理Java类型与数据库类型之间的特殊转换。例如将Java的List 转换为数据库中以逗号分隔的字符串public class StringListTypeHandler extends BaseTypeHandlerListString { Override public void setNonNullParameter(PreparedStatement ps, int i, ListString parameter, JdbcType jdbcType) throws SQLException { ps.setString(i, String.join(,, parameter)); } Override public ListString getNullableResult(ResultSet rs, String columnName) throws SQLException { String value rs.getString(columnName); return value null ? null : Arrays.asList(value.split(,)); } // 其他重载方法... }在Mapper XML中使用这个类型处理器resultMap iduserResultMap typeUser result propertytags columntags typeHandlercom.example.handler.StringListTypeHandler/ /resultMap7. 实际项目中的经验分享在大型项目中MyBatis的配置和管理有一些值得注意的经验Mapper接口的命名规范保持接口名与XML文件名一致如UserMapper.java对应UserMapper.xml可以减少配置错误SQL片段重用使用 标签定义可重用的SQL片段避免重复代码sql iduserColumnsid,name,email,create_time/sql select idfindAll resultMapuserResultMap SELECT include refiduserColumns/ FROM users /select分页处理虽然MyBatis有RowBounds实现分页但在大数据量下性能不佳。推荐使用PageHelper插件或手动编写分页SQL多数据源配置在需要连接多个数据库的场景下可以通过配置多个SqlSessionFactory来实现Configuration MapperScan(basePackages com.example.mapper.primary, sqlSessionFactoryRef primarySqlSessionFactory) public class PrimaryDataSourceConfig { Bean ConfigurationProperties(spring.datasource.primary) public DataSource primaryDataSource() { return DataSourceBuilder.create().build(); } Bean public SqlSessionFactory primarySqlSessionFactory( Qualifier(primaryDataSource) DataSource dataSource) throws Exception { SqlSessionFactoryBean factoryBean new SqlSessionFactoryBean(); factoryBean.setDataSource(dataSource); return factoryBean.getObject(); } // 其他配置... }SQL审查在团队开发中建议建立SQL审查机制特别是对于复杂的SQL语句确保其性能和正确性测试策略为Mapper层编写单元测试时可以使用内存数据库如H2或者利用MyBatis-Spring提供的MybatisTest注解MybatisTest AutoConfigureTestDatabase(replace Replace.NONE) public class UserMapperTest { Autowired private UserMapper userMapper; Test public void testFindById() { User user userMapper.findById(1L); assertNotNull(user); } }与MyBatis-Plus的对比MyBatis-Plus在基础MyBatis上提供了更多便利功能如通用Mapper、Lambda查询等。但在需要高度定制SQL的场景下原生MyBatis仍然更具优势XML管理技巧对于大型项目建议按业务模块拆分XML文件而不是将所有SQL都放在一个巨大的文件中。同时保持XML中的SQL格式统一便于阅读和维护日志配置开发阶段可以开启MyBatis的SQL日志方便调试logging.level.com.example.mapperDEBUG与Spring Boot的深度集成Spring Boot为MyBatis提供了许多自动配置项如mybatis.configuration.map-underscore-to-camel-casetrue可以自动将下划线列名映射为驼峰属性名减少手动配置的工作量
RELATED

相关推荐

MySQL选型决策:自建vs阿里云瑶池RDS四维成本对比

MySQL选型决策:自建vs阿里云瑶池RDS四维成本对比

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/14 1:45:31
PeakTech P1260台式示波器:12位ADC+触摸屏的产线级实用主义选择

PeakTech P1260台式示波器:12位ADC+触摸屏的产线级实用主义选择

1. 这台“P1260”不是玩具,是能扛起产线调试、教学验证和维修诊断三重任务的台式示波器 PeakTech台式示波器P1260——这个型号名一出现,我就知道它不是冲着“网红爆款”去的,而是奔着实验室抽屉里那台总在关键时刻掉链子的老款模拟机、学校电…

📅 2026/9/14 1:40:31
SpringBoot实现企业级Wiki系统的RBAC权限管理

SpringBoot实现企业级Wiki系统的RBAC权限管理

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

📅 2026/9/14 1:40:31
MORE NEWS

更多资讯

📰

超外差接收机本振泄露原理与SDR探测定位实战指南

做无线电监测和软件定义无线电(SDR)这么多年,我一直觉得有一个现象特别有意思:一台明明只负责“收”信号的设备,居然也能被外面的人发现,甚至被定位。很多人天然的认知是,只要我不发射、不主动“…

📰

SEO分析软件核心价值与实战应用解析

1. SEO分析软件的核心价值解析当网站流量增长陷入瓶颈时,SEO分析软件往往成为破局的关键工具。这类工具通过技术手段抓取并解析搜索引擎的运作规律,将抽象的SEO策略转化为可视化的数据指标。以Ahrefs为例,其站点审计功能能自动检测出影响排名…

📰

Python去哪儿景点爬虫:从requests请求到并发存储的完整设计

简介:基于Python的旅游景点爬虫(去哪网)设计源码是一份面向爬虫初学者、旅游数据分析及毕业设计场景的实战项目。它以去哪网为目标站点,演示了景区信息采集、清洗与结构化存储的完整流程,覆盖国内多省市及亚洲、欧洲、…

📰

MATLAB实现802.11a OFDM同步与信道估计全流程

简介:本资源是一份面向通信工程与信号处理方向本科生的课程设计实践材料,聚焦802.11a标准下OFDM系统的MATLAB仿真实现,重点解决无线信道估计与符号定时同步两大核心问题,适用于数字通信原理、现代通信技术等课程的实验拓展与课程设…

📰

VC/MFC对话框添加工具栏:布局原理与实现要点

简介:面向Visual C开发者,这份资源演示了如何在MFC对话框程序中加入并管理工具栏,帮助解决界面交互增强与按钮消息响应问题。压缩包共19个文件,以.h头文件、.cpp源文件为主,包含对话框类、视图/文档类及主框架实现&…

📰

Go 无 CGo 接入 SQLite 3:zombiezen.com/go/sqlite 使用指南与 Loki 实战

Go 无 CGo 接入 SQLite 3:zombiezen.com/go/sqlite 使用指南与 Loki 实战 【免费下载链接】loki Like Prometheus, but for logs. 项目地址: https://gitcode.com/GitHub_Trending/lok/loki zombiezen.com/go/sqlite 是一个面向 Go 的 SQLite 3 底层接口库&a…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬