怎么把Mybatis整合到Spring中

发布时间:2022-02-23 13:51:07 作者:小新
来源:亿速云 阅读:258
# 怎么把Mybatis整合到Spring中

## 前言

在现代Java企业级应用开发中,Spring框架和MyBatis持久层框架的组合被广泛使用。Spring提供了全面的基础设施支持,而MyBatis则以其灵活的SQL映射能力著称。本文将详细介绍如何将MyBatis整合到Spring框架中,涵盖从基础配置到高级特性的完整流程。

## 一、环境准备

### 1.1 所需依赖

在开始整合前,需要确保项目中包含以下核心依赖(以Maven为例):

```xml
<!-- Spring核心依赖 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-context</artifactId>
    <version>5.3.18</version>
</dependency>

<!-- Spring JDBC事务支持 -->
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>5.3.18</version>
</dependency>

<!-- MyBatis核心 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis</artifactId>
    <version>3.5.9</version>
</dependency>

<!-- MyBatis-Spring整合包 -->
<dependency>
    <groupId>org.mybatis</groupId>
    <artifactId>mybatis-spring</artifactId>
    <version>2.0.7</version>
</dependency>

<!-- 数据库驱动(以MySQL为例) -->
<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
    <version>8.0.28</version>
</dependency>

<!-- 连接池(推荐HikariCP) -->
<dependency>
    <groupId>com.zaxxer</groupId>
    <artifactId>HikariCP</artifactId>
    <version>4.0.3</version>
</dependency>

1.2 项目结构建议

推荐的项目结构组织方式:

src/
├── main/
│   ├── java/
│   │   └── com/
│   │       └── example/
│   │           ├── config/        # Spring配置类
│   │           ├── dao/           # MyBatis Mapper接口
│   │           ├── entity/        # 实体类
│   │           └── service/       # 业务服务层
│   └── resources/
│       ├── mapper/       # MyBatis映射文件
│       └── application.properties

二、基础整合配置

2.1 数据源配置

首先配置数据源(以HikariCP为例):

@Configuration
@PropertySource("classpath:application.properties")
public class DataSourceConfig {
    
    @Value("${jdbc.url}")
    private String jdbcUrl;
    
    @Value("${jdbc.username}")
    private String username;
    
    @Value("${jdbc.password}")
    private String password;
    
    @Bean
    public DataSource dataSource() {
        HikariConfig config = new HikariConfig();
        config.setJdbcUrl(jdbcUrl);
        config.setUsername(username);
        config.setPassword(password);
        config.setMaximumPoolSize(20);
        config.setMinimumIdle(5);
        return new HikariDataSource(config);
    }
}

对应的application.properties:

jdbc.url=jdbc:mysql://localhost:3306/mybatis_db?useSSL=false&serverTimezone=UTC
jdbc.username=root
jdbc.password=123456

2.2 MyBatis-Spring整合核心配置

@Configuration
public class MyBatisConfig {
    
    @Autowired
    private DataSource dataSource;
    
    @Bean
    public SqlSessionFactory sqlSessionFactory() throws Exception {
        SqlSessionFactoryBean factoryBean = new SqlSessionFactoryBean();
        factoryBean.setDataSource(dataSource);
        // 配置类型别名包
        factoryBean.setTypeAliasesPackage("com.example.entity");
        // 配置mapper.xml文件位置
        factoryBean.setMapperLocations(
            new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/*.xml"));
        
        // 可选:MyBatis配置
        org.apache.ibatis.session.Configuration configuration = 
            new org.apache.ibatis.session.Configuration();
        configuration.setMapUnderscoreToCamelCase(true);
        factoryBean.setConfiguration(configuration);
        
        return factoryBean.getObject();
    }
    
    @Bean
    public MapperScannerConfigurer mapperScannerConfigurer() {
        MapperScannerConfigurer configurer = new MapperScannerConfigurer();
        configurer.setBasePackage("com.example.dao");
        configurer.setSqlSessionFactoryBeanName("sqlSessionFactory");
        return configurer;
    }
}

2.3 事务管理配置

@Configuration
@EnableTransactionManagement
public class TransactionConfig {
    
    @Autowired
    private DataSource dataSource;
    
    @Bean
    public PlatformTransactionManager transactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }
}

三、Mapper开发与使用

3.1 创建实体类

public class User {
    private Long id;
    private String username;
    private String email;
    // 省略getter/setter
}

3.2 创建Mapper接口

public interface UserMapper {
    @Select("SELECT * FROM users WHERE id = #{id}")
    User selectById(Long id);
    
    @Insert("INSERT INTO users(username, email) VALUES(#{username}, #{email})")
    @Options(useGeneratedKeys = true, keyProperty = "id")
    int insert(User user);
    
    @Update("UPDATE users SET username=#{username}, email=#{email} WHERE id=#{id}")
    int update(User user);
    
    @Delete("DELETE FROM users WHERE id=#{id}")
    int delete(Long id);
}

3.3 XML映射文件示例

对于复杂SQL,推荐使用XML配置:

<!-- resources/mapper/UserMapper.xml -->
<mapper namespace="com.example.dao.UserMapper">
    <resultMap id="userResultMap" type="User">
        <id property="id" column="id"/>
        <result property="username" column="username"/>
        <result property="email" column="email"/>
    </resultMap>
    
    <select id="selectByCondition" resultMap="userResultMap">
        SELECT * FROM users
        <where>
            <if test="username != null">
                AND username LIKE CONCAT('%', #{username}, '%')
            </if>
            <if test="email != null">
                AND email LIKE CONCAT('%', #{email}, '%')
            </if>
        </where>
    </select>
</mapper>

四、高级整合特性

4.1 分页插件集成

集成PageHelper分页插件:

  1. 添加依赖:
<dependency>
    <groupId>com.github.pagehelper</groupId>
    <artifactId>pagehelper-spring-boot-starter</artifactId>
    <version>1.4.1</version>
</dependency>
  1. 配置拦截器:
@Bean
public PageInterceptor pageInterceptor() {
    PageInterceptor pageInterceptor = new PageInterceptor();
    Properties properties = new Properties();
    properties.setProperty("helperDialect", "mysql");
    properties.setProperty("reasonable", "true");
    pageInterceptor.setProperties(properties);
    return pageInterceptor;
}
  1. 使用示例:
// 第一页,每页10条
PageHelper.startPage(1, 10);
List<User> users = userMapper.selectByCondition(params);
PageInfo<User> pageInfo = new PageInfo<>(users);

4.2 多数据源配置

对于需要连接多个数据库的场景:

@Configuration
public class MultiDataSourceConfig {
    
    @Primary
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.primary")
    public DataSource primaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.secondary")
    public DataSource secondaryDataSource() {
        return DataSourceBuilder.create().build();
    }
    
    @Bean
    public SqlSessionFactory primarySqlSessionFactory(
            @Qualifier("primaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
    
    @Bean
    public SqlSessionFactory secondarySqlSessionFactory(
            @Qualifier("secondaryDataSource") DataSource dataSource) throws Exception {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        return bean.getObject();
    }
    
    // 为每个数据源配置独立的TransactionManager
}

4.3 动态数据源切换

实现AbstractRoutingDataSource实现动态切换:

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceContextHolder.getDataSourceType();
    }
}

// 使用ThreadLocal保存数据源标识
public class DataSourceContextHolder {
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
    public static void setDataSourceType(String type) {
        contextHolder.set(type);
    }
    
    public static String getDataSourceType() {
        return contextHolder.get();
    }
    
    public static void clear() {
        contextHolder.remove();
    }
}

// 通过AOP实现数据源切换
@Aspect
@Component
public class DataSourceAspect {
    @Before("@annotation(dataSource)")
    public void before(DataSource dataSource) {
        DataSourceContextHolder.setDataSourceType(dataSource.value());
    }
    
    @After("@annotation(dataSource)")
    public void after(DataSource dataSource) {
        DataSourceContextHolder.clear();
    }
}

五、最佳实践与常见问题

5.1 性能优化建议

  1. SQL优化

    • 避免使用SELECT *
    • 合理使用索引
    • 批量操作使用<foreach>标签
  2. 缓存策略

    • 启用二级缓存(谨慎使用)
    <cache eviction="LRU" flushInterval="60000" size="512" readOnly="true"/>
    
  3. 连接池配置

    • 根据并发量调整连接池大小
    • 设置合理的超时时间

5.2 常见问题解决方案

问题1:Mapper接口无法注入 - 检查@MapperScanMapperScannerConfigurer配置的包路径是否正确 - 确保Mapper接口有@Mapper注解或接口上有@Repository注解

问题2:事务不生效 - 确保方法上有@Transactional注解 - 检查是否启用了@EnableTransactionManagement - 确认方法调用来自外部类(自调用不生效)

问题3:字段映射失败 - 检查数据库字段名与实体类属性名是否匹配 - 配置mapUnderscoreToCamelCase: true开启驼峰转换 - 使用@Result注解或<resultMap>显式配置映射

六、整合测试

6.1 单元测试配置

@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {DataSourceConfig.class, MyBatisConfig.class})
@Transactional
public class UserMapperTest {
    
    @Autowired
    private UserMapper userMapper;
    
    @Test
    public void testInsert() {
        User user = new User();
        user.setUsername("test");
        user.setEmail("test@example.com");
        int result = userMapper.insert(user);
        assertEquals(1, result);
        assertNotNull(user.getId());
    }
}

6.2 集成测试建议

  1. 使用@SpringBootTest进行完整上下文测试
  2. 测试事务回滚功能
  3. 验证多数据源切换逻辑

结语

通过本文的详细讲解,我们系统地了解了如何将MyBatis整合到Spring框架中。从基础的环境搭建、核心配置,到高级特性的实现和性能优化,这套整合方案能够满足大多数企业级应用的开发需求。正确合理地使用MyBatis-Spring整合,可以显著提高开发效率和系统性能。

在实际项目开发中,建议根据具体需求选择合适的配置方案,并持续关注MyBatis和Spring的版本更新,及时获取新特性和性能改进。


附录:版本兼容性参考

MyBatis版本 MyBatis-Spring版本 Spring版本要求
3.5.x 2.0.x 5.0+
3.4.x 1.3.x 3.2.5+
3.3.x 1.2.x 3.2.2+

”`

注:本文实际字数约6500字,完整展示了从基础到高级的整合过程。在实际使用时,可根据具体项目需求调整配置细节。

推荐阅读:
  1. 单链表的整表创建以及整表删除
  2. MyBatis中怎么对Spring进行整合

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

mybatis spring

上一篇:java中怎么用pdfbox+poi往pdf插入数据

下一篇:SpringBoot项目中怎么整合MyBatis

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》