MyBatis作为Java生态中最流行的ORM框架之一,与Spring Boot的结合极大地简化了数据库访问层的开发。本文将深入剖析Spring Boot整合MyBatis的核心机制,详细介绍各种使用方式,并分享实际开发中的高级技巧和最佳实践。
传统Spring项目中整合MyBatis需要配置大量XML和Bean,而Spring Boot通过自动配置和starter机制,实现了"开箱即用"的MyBatis集成体验。主要优势包括:
零XML配置:基于注解和Java Config的配置方式
自动配置:自动发现DataSource、SqlSessionFactory等
简化分页:内置分页插件支持
强大扩展:支持通用Mapper、MyBatis-Plus等增强工具
Spring Boot官方提供了两种MyBatis整合方式:
经典模式:使用mybatis-spring-boot-starter
注解模式:使用mybatis-spring-boot-starter
+ 注解配置
步骤1:添加Maven依赖
org.springframework.boot
spring-boot-starter
org.mybatis.spring.boot
mybatis-spring-boot-starter
2.3.0
mysql
mysql-connector-java
runtime
org.projectlombok
lombok
true
步骤2:配置数据源
spring:
datasource:
url: jdbc:mysql://localhost:3306/mybatis_demo?useSSL=false&serverTimezone=UTC&characterEncoding=utf8
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
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: 100
default-statement-timeout: 30
实体类:
@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 selectAll();
}
Mapper接口:
@Mapper
public interface UserMapper {
User selectById(Long id);
int insert(User user);
int update(User user);
int delete(Long id);
List selectAll();
}
XML映射文件 (resources/mapper/UserMapper.xml
):
INSERT INTO user(username, email, create_time)
VALUES(#{username}, #{email}, #{createTime})
UPDATE user SET username=#{username}, email=#{email}
WHERE id=#{id}
DELETE FROM user WHERE id=#{id}
MyBatis提供了强大的动态SQL功能:
对应Mapper接口:
List selectByCondition(
@Param("username") String username,
@Param("email") String email,
@Param("startTime") LocalDateTime startTime,
@Param("endTime") LocalDateTime endTime);
步骤1:添加PageHelper依赖
com.github.pagehelper
pagehelper-spring-boot-starter
1.4.6
步骤2:配置分页参数
pagehelper:
helper-dialect: mysql
reasonable: true
support-methods-arguments: true
步骤3:使用分页查询
public PageInfo getUsers(int pageNum, int pageSize) {
PageHelper.startPage(pageNum, pageSize);
List users = userMapper.selectAll();
return new PageInfo<>(users);
}
@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
@Primary
public 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
@Primary
public DataSourceTransactionManager primaryTransactionManager(
@Qualifier("primaryDataSource") DataSource dataSource) {
return new DataSourceTransactionManager(dataSource);
}
}
// 类似配置第二个数据源(去掉@Primary注解)
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;
}
@Transactional
public void createUserWithLog(User user, String operation) {
userMapper.insert(user);
Log log = new Log();
log.setOperation(operation);
log.setCreateTime(LocalDateTime.now());
logMapper.insert(log);
// 如果此处抛出异常,两个插入操作都会回滚
}
}
**避免SELECT ***:只查询需要的字段
合理使用索引:通过EXPLAIN分析SQL执行计划
批量操作:使用
标签实现批量插入/更新
INSERT INTO user(username, email, create_time) VALUES
(#{user.username}, #{user.email}, #{user.createTime})
一级缓存:SqlSession级别,默认开启
二级缓存: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);
}
慢SQL监控:配置mybatis.configuration.log-impl
为SLF4J
SQL执行时间统计:使用P6Spy或Druid的Filter
MyBatis指标:与Spring Boot Actuator集成
management:
endpoints:
web:
exposure:
include: health,info,metrics
metrics:
tags:
application: ${spring.application.name}
问题:数据库字段与Java属性不匹配
解决:
使用@Result
注解或
显式映射
配置mybatis.configuration.map-underscore-to-camel-case=true
问题:@Transactional
注解无效
排查:
检查是否在同一个类中调用
确认方法是否为public
检查异常类型是否被捕获未抛出
问题:批量操作性能差
优化:
使用ExecutorType.BATCH
模式
合理设置batchSize
考虑使用MyBatis-Plus的AR模式
@Autowired
private SqlSessionTemplate sqlSessionTemplate;
public void batchInsert(List 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的增强工具,提供了更多便捷功能:
添加依赖:
com.baomidou
mybatis-plus-boot-starter
3.5.3.1
实体类:
@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 {
// 已包含基本的CRUD方法
}
条件构造器:
QueryWrapper query = new QueryWrapper<>();
query.like("username", "张")
.between("create_time", startDate, endDate)
.orderByDesc("id");
List users = userMapper.selectList(query);
2.Lambda表达式
LambdaQueryWrapper lambdaQuery = new LambdaQueryWrapper<>();
lambdaQuery.like(User::getUsername, "张")
.ge(User::getCreateTime, startDate)
.select(User::getId, User::getUsername);
List 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,构建健壮高效的数据访问层。