SpringBoot+MyBatis集成进阶配置 - XML与注解的灵活运用
前言
在Spring Boot与MyBatis的集成开发中,开发者常面临XML映射文件 与注解 两种SQL定义方式的选择,以及复杂场景下的动态SQL、多数据源等进阶需求。本文将从核心配置的灵活性出发,对比XML与注解的适用场景,详解动态SQL的实现技巧,并结合ResultMap
、typeAliases
等高级特性,最终通过多数据源配置实战演示企业级解决方案。无论你是希望优化现有项目,还是应对复杂业务逻辑,本文均能提供清晰的实践路径。
一、XML与注解:如何选择?
1. 注解的简洁与局限
通过@Select
、@Insert
等注解直接在Mapper接口中编写SQL,适合简单、静态的SQL场景,例如:
java
@Select("SELECT * FROM user WHERE id = #{id}")
User findById(Long id);
优点:
- 代码简洁,无需维护XML文件。
- 适合快速开发小型项目。
缺点**:
- 复杂SQL可读性差(如动态条件、关联查询)。
- 无法直接使用MyBatis的动态SQL标签。
2. XML的动态与强大
XML映射文件通过<if>
、<foreach>
等标签支持动态SQL,适合复杂查询和批量操作:
xml
<select id="findUsers" resultType="User">
SELECT * FROM user
<where>
<if test="name != null">AND name = #{name}</if>
<if test="status != null">AND status = #{status}</if>
</where>
</select>
优点:
- 动态SQL灵活,易于维护复杂逻辑。
- 支持结果集映射(
ResultMap
)和关联查询。
缺点:
- 需额外维护XML文件,项目结构稍显复杂。
结论 :简单查询用注解,复杂逻辑用XML,二者可混合使用!
二、动态SQL实战:提升代码灵活性
1. 条件分支与循环
<if>
标签:根据参数动态拼接条件。<foreach>
标签:实现批量插入或IN查询:
xml
<insert id="batchInsert">
INSERT INTO user (name, email) VALUES
<foreach item="user" collection="list" separator=",">
(#{user.name}, #{user.email})
</foreach>
</insert>
2. 多表关联查询与ResultMap
通过ResultMap
定义嵌套结果集,解决一对多关联查询:
xml
<resultMap id="OrderWithItems" type="Order">
<id property="id" column="order_id"/>
<collection property="items" ofType="OrderItem">
<id property="id" column="item_id"/>
<result property="product" column="product_name"/>
</collection>
</resultMap>
三、核心配置优化:typeAliases与mapperLocations
1. 简化实体类引用
在application.yml
中配置type-aliases-package
,避免XML中写全类名:
yaml
mybatis:
type-aliases-package: com.example.entity
mapper-locations: classpath:mapper/*.xml
2. 自动扫描Mapper接口
通过@MapperScan
注解指定Mapper接口路径,避免逐个添加@Mapper
:
java
@SpringBootApplication
@MapperScan("com.example.mapper")
public class Application { ... }
四、多数据源配置实战
场景需求
同时连接主库(写操作)和从库(读操作),需独立配置数据源与MyBatis会话。
1. 主数据源配置
java
@Configuration
@MapperScan(basePackages = "com.example.mapper.primary", sqlSessionFactoryRef = "primarySqlSessionFactory")
public class PrimaryDataSourceConfig {
@Bean(name = "primaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.primary")
public DataSource primaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "primarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/primary/*.xml"));
return bean.getObject();
}
}
2. 从数据源配置
java
@Configuration
@MapperScan(basePackages = "com.example.mapper.secondary", sqlSessionFactoryRef = "secondarySqlSessionFactory")
public class SecondaryDataSourceConfig {
@Bean(name = "secondaryDataSource")
@ConfigurationProperties(prefix = "spring.datasource.secondary")
public DataSource secondaryDataSource() {
return DataSourceBuilder.create().build();
}
@Bean(name = "secondarySqlSessionFactory")
public SqlSessionFactory sqlSessionFactory(@Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
bean.setDataSource(dataSource);
bean.setMapperLocations(new PathMatchingResourcePatternResolver().getResources("classpath:mapper/secondary/*.xml"));
return bean.getObject();
}
}
3. 配置文件(application.yml)
yaml
spring:
datasource:
primary:
url: jdbc:mysql://localhost:3306/primary_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
secondary:
url: jdbc:mysql://localhost:3306/secondary_db
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
五、总结与最佳实践
- XML与注解混合使用:简单CRUD用注解,动态SQL和关联查询用XML。
- 动态SQL提升灵活性 :善用
<if>
、<foreach>
处理复杂业务逻辑。 - 配置优化技巧 :
type-aliases-package
简化代码,mapperLocations
规范路径。 - 多数据源方案 :通过独立配置
DataSource
和SqlSessionFactory
实现读写分离。
避坑指南:
- 多数据源场景下,需明确指定
@MapperScan
的sqlSessionFactoryRef
属性。 - 避免在多数据源中重复扫描同一Mapper接口路径。
欢迎在评论区留言讨论你在MyBatis配置中遇到的难题!