MyBatis作为Java生态中最流行的ORM框架之一,与Spring Boot的结合极大地简化了数据库访问层的开发。本文将深入剖析Spring Boot整合MyBatis的核心机制,详细介绍各种使用方式,并分享实际开发中的高级技巧和最佳实践。
一、Spring Boot与MyBatis整合概述
1.1 整合背景与优势
传统Spring项目中整合MyBatis需要配置大量XML和Bean,而Spring Boot通过自动配置和starter机制,实现了"开箱即用"的MyBatis集成体验。主要优势包括:
-
零XML配置:基于注解和Java Config的配置方式
-
自动配置:自动发现DataSource、SqlSessionFactory等
-
简化分页:内置分页插件支持
-
强大扩展:支持通用Mapper、MyBatis-Plus等增强工具
1.2 官方支持的整合方式
Spring Boot官方提供了两种MyBatis整合方式:
-
经典模式:使用
mybatis-spring-boot-starter
-
注解模式:使用
mybatis-spring-boot-starter
+ 注解配置
二、快速整合实战
2.1 基础环境搭建
步骤1:添加Maven依赖
<dependencies><!-- Spring Boot Starter --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter</artifactId></dependency><!-- MyBatis Starter --><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.3.0</version></dependency><!-- 数据库驱动 --><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><scope>runtime</scope></dependency><!-- 其他必要依赖 --><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency>
</dependencies>
步骤2:配置数据源
spring:datasource:url: jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC&characterEncoding=utf8username: rootpassword: 123456driver-class-name: com.mysql.cj.jdbc.Driver
2.2 自动配置原理剖析
Spring Boot通过MybatisAutoConfiguration
类实现自动配置,核心机制包括:
-
SqlSessionFactory自动创建:基于配置的DataSource
-
Mapper扫描注册:通过
@MapperScan
或@Mapper
注解 -
事务管理集成:与Spring事务无缝整合
关键自动配置属性:
mybatis:config-location: classpath:mybatis/mybatis-config.xml # 全局配置文件路径mapper-locations: classpath:mybatis/mapper/*.xml # Mapper XML文件位置type-aliases-package: com.example.model # 类型别名包configuration: # MyBatis配置项map-underscore-to-camel-case: true # 下划线转驼峰default-fetch-size: 100default-statement-timeout: 30
三、MyBatis基础使用
3.1 注解方式开发
实体类:
@Data
public class User {private Long id;private String username;private String email;private LocalDateTime createTime;
}
Mapper接口:
@Mapper
public interface UserMapper {@Select("SELECT * FROM user WHERE id = #{id}")User selectById(Long id);@Insert("INSERT INTO user(username, email, create_time) " +"VALUES(#{username}, #{email}, #{createTime})")@Options(useGeneratedKeys = true, keyProperty = "id")int insert(User user);@Update("UPDATE user SET username=#{username}, email=#{email} WHERE id=#{id}")int update(User user);@Delete("DELETE FROM user WHERE id=#{id}")int delete(Long id);@Select("SELECT * FROM user")List<User> selectAll();
}
3.2 XML方式开发
Mapper接口:
@Mapper
public interface UserMapper {User selectById(Long id);int insert(User user);int update(User user);int delete(Long id);List<User> selectAll();
}
XML映射文件 (resources/mapper/UserMapper.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.mapper.UserMapper"><resultMap id="userResultMap" type="User"><id property="id" column="id"/><result property="username" column="username"/><result property="email" column="email"/><result property="createTime" column="create_time"/></resultMap><select id="selectById" resultMap="userResultMap">SELECT * FROM user WHERE id = #{id}</select><insert id="insert" useGeneratedKeys="true" keyProperty="id">INSERT INTO user(username, email, create_time)VALUES(#{username}, #{email}, #{createTime})</insert><update id="update">UPDATE user SET username=#{username}, email=#{email}WHERE id=#{id}</update><delete id="delete">DELETE FROM user WHERE id=#{id}</delete><select id="selectAll" resultMap="userResultMap">SELECT * FROM user</select>
</mapper>
3.3 动态SQL应用
MyBatis提供了强大的动态SQL功能:
<select id="selectByCondition" resultMap="userResultMap">SELECT * FROM user<where><if test="username != null and username != ''">AND username LIKE CONCAT('%', #{username}, '%')</if><if test="email != null and email != ''">AND email = #{email}</if><if test="startTime != null">AND create_time >= #{startTime}</if><if test="endTime != null">AND create_time <= #{endTime}</if></where>ORDER BY id DESC
</select>
对应Mapper接口:
List<User> selectByCondition(@Param("username") String username,@Param("email") String email,@Param("startTime") LocalDateTime startTime,@Param("endTime") LocalDateTime endTime);
四、高级特性与集成
4.1 分页插件集成
步骤1:添加PageHelper依赖
<dependency><groupId>com.github.pagehelper</groupId><artifactId>pagehelper-spring-boot-starter</artifactId><version>1.4.6</version>
</dependency>
步骤2:配置分页参数
pagehelper:helper-dialect: mysqlreasonable: truesupport-methods-arguments: true
步骤3:使用分页查询
public PageInfo<User> getUsers(int pageNum, int pageSize) {PageHelper.startPage(pageNum, pageSize);List<User> users = userMapper.selectAll();return new PageInfo<>(users);
}
4.2 多数据源配置
@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {@Bean@Primary@ConfigurationProperties("spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean@Primarypublic SqlSessionFactory primarySqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();factoryBean.setDataSource(dataSource);factoryBean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*.xml"));return factoryBean.getObject();}@Bean@Primarypublic DataSourceTransactionManager primaryTransactionManager(@Qualifier("primaryDataSource") DataSource dataSource) {return new DataSourceTransactionManager(dataSource);}
}// 类似配置第二个数据源(去掉@Primary注解)
4.3 事务管理
Spring Boot自动配置了基于Spring的事务管理,只需使用@Transactional
注解:
@Service
public class UserService {private final UserMapper userMapper;private final LogMapper logMapper;public UserService(UserMapper userMapper, LogMapper logMapper) {this.userMapper = userMapper;this.logMapper = logMapper;}@Transactionalpublic void createUserWithLog(User user, String operation) {userMapper.insert(user);Log log = new Log();log.setOperation(operation);log.setCreateTime(LocalDateTime.now());logMapper.insert(log);// 如果此处抛出异常,两个插入操作都会回滚}
}
五、性能优化与最佳实践
5.1 SQL优化建议
-
**避免SELECT ***:只查询需要的字段
-
合理使用索引:通过EXPLAIN分析SQL执行计划
-
批量操作:使用
<foreach>
标签实现批量插入/更新
<insert id="batchInsert">INSERT INTO user(username, email, create_time) VALUES<foreach collection="users" item="user" separator=",">(#{user.username}, #{user.email}, #{user.createTime})</foreach>
</insert>
5.2 缓存配置
一级缓存:SqlSession级别,默认开启
二级缓存:Mapper级别,需要显式开启:
<mapper namespace="com.example.mapper.UserMapper"><cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>...
</mapper>
与Spring Cache集成:
@CacheConfig(cacheNames = "users")
public interface UserMapper {@Cacheable(key = "#id")@Select("SELECT * FROM user WHERE id = #{id}")User selectById(Long id);@CacheEvict(allEntries = true)@Update("UPDATE user SET username=#{username} WHERE id=#{id}")int updateUsername(@Param("id") Long id, @Param("username") String username);
}
5.3 监控与诊断
-
慢SQL监控:配置
mybatis.configuration.log-impl
为SLF4J -
SQL执行时间统计:使用P6Spy或Druid的Filter
-
MyBatis指标:与Spring Boot Actuator集成
management:endpoints:web:exposure:include: health,info,metricsmetrics:tags:application: ${spring.application.name}
六、常见问题解决方案
6.1 映射问题
问题:数据库字段与Java属性不匹配
解决:
-
使用
@Result
注解或<resultMap>
显式映射 -
配置
mybatis.configuration.map-underscore-to-camel-case=true
6.2 事务不生效
问题:@Transactional
注解无效
排查:
-
检查是否在同一个类中调用
-
确认方法是否为public
-
检查异常类型是否被捕获未抛出
6.3 性能问题
问题:批量操作性能差
优化:
-
使用
ExecutorType.BATCH
模式 -
合理设置
batchSize
-
考虑使用MyBatis-Plus的AR模式
@Autowired
private SqlSessionTemplate sqlSessionTemplate;public void batchInsert(List<User> users) {SqlSession session = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);try {UserMapper mapper = session.getMapper(UserMapper.class);for (User user : users) {mapper.insert(user);}session.commit();} finally {session.close();}
}
七、MyBatis-Plus扩展
MyBatis-Plus是MyBatis的增强工具,提供了更多便捷功能:
7.1 快速入门
添加依赖:
<dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.3.1</version>
</dependency>
实体类:
@Data
@TableName("user")
public class User {@TableId(type = IdType.AUTO)private Long id;private String username;private String email;private LocalDateTime createTime;
}
Mapper接口:
public interface UserMapper extends BaseMapper<User> {// 已包含基本的CRUD方法
}
7.2 强大功能
-
条件构造器:
QueryWrapper<User> query = new QueryWrapper<>();
query.like("username", "张").between("create_time", startDate, endDate).orderByDesc("id");
List<User> users = userMapper.selectList(query);
2.Lambda表达式
LambdaQueryWrapper<User> lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.like(User::getUsername, "张").ge(User::getCreateTime, startDate).select(User::getId, User::getUsername);
List<User> users = userMapper.selectList(lambdaQuery);
3.自动填充
@TableField(fill = FieldFill.INSERT)
private LocalDateTime createTime;@TableField(fill = FieldFill.INSERT_UPDATE)
private LocalDateTime updateTime;
结语
Spring Boot与MyBatis的整合为Java开发者提供了高效、灵活的数据访问解决方案。通过本文的介绍,您应该已经掌握了从基础配置到高级特性的全面知识。在实际项目中,建议:
-
根据项目规模选择合适的开发模式(注解/XML)
-
合理利用MyBatis的动态SQL能力
-
关注性能优化,特别是批量操作场景
-
考虑使用MyBatis-Plus等增强工具提升开发效率
希望本文能帮助您在Spring Boot项目中更好地使用MyBatis,构建健壮高效的数据访问层。