spring学习7: 纯注解整合mybatis和事务控制

本文记录下如何利用纯注解的方式整合spring和mybatis

一、引入依赖

需要引入的依赖包括spring、mybatis、mybatis-spring、数据库驱动、连接池

<dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-jdbc</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-tx</artifactId>
            <version>5.1.5.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis-spring</artifactId>
            <version>1.3.2</version>
        </dependency>

        <dependency>
            <groupId>org.mybatis</groupId>
            <artifactId>mybatis</artifactId>
            <version>3.4.5</version>
        </dependency>

        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.46</version>
        </dependency>

        <!--连接池-->
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid</artifactId>
            <version>1.1.11</version>
        </dependency>

二、整合过程

2.1 整合原理

本文中sql语句是写在xml文件中的

mybatis-spring提供了一个SqlSessionFactoryBean类,创建该类的对象添加到容器中,然后再用MapperScan注解指定要扫描的dao层接口的包路径。

其中sql文件的路径和需要起别名的实体类包名均可以在SqlSessionFactoryBean对象中进行配置。

2.2 配置类编写

创建配置类MyApplication.java,在配置类上使用注解MapperScan指定dao层接口扫描路径,使用PropertySource注解加载外部properties配置文件;在配置类中使用@value注解读取properties文件的内容到成员变量中;配置连接池的bean对象;配置SqlSessionFactoryBean的对象

package com.lyy;

import com.alibaba.druid.pool.DruidDataSource;
import com.lyy.service.UserService;
import org.mybatis.spring.SqlSessionFactoryBean;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.PropertySource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;

import javax.sql.DataSource;
import java.io.IOException;

@Configuration
@ComponentScan("com.lyy")//bean扫描路径
@MapperScan("com.lyy.mapper")
@PropertySource({"classpath:db.properties"})//加载外部配置文件
public class MyApplication {

    @Value("${jdbc.username}")
    private String username;

    @Value("${jdbc.password}")
    private String password;

    @Value("${jdbc.driver}")
    private String driverClassName;

    @Value("${jdbc.url}")
    private String jdbcUrl;



    @Bean
    public DataSource dataSource(){
        DruidDataSource dataSource=new DruidDataSource();
        dataSource.setUsername(username);
        dataSource.setPassword(password);
        dataSource.setDriverClassName(driverClassName);
        dataSource.setUrl(jdbcUrl);
        return dataSource;
    }

    @Bean
    public SqlSessionFactoryBean sessionFactoryBean() throws IOException {
        SqlSessionFactoryBean sqlSessionFactoryBean =new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource());
        //指定sql xml文件的位置,文件位置和dao接口的包路径一致时可以不指定
        sqlSessionFactoryBean.setMapperLocations(new PathMatchingResourcePatternResolver()
                .getResources("classpath:mapper/*.xml"));
        sqlSessionFactoryBean.setTypeAliasesPackage("com.lyy.vo");
        return sqlSessionFactoryBean;
    }


    public static void main(String[] args) {
        AnnotationConfigApplicationContext app=new AnnotationConfigApplicationContext(MyApplication.class);
        UserService userService = app.getBean(UserService.class);
        userService.test();
    }
}

2.3 sql文件示例

<?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.lyy.mapper.UserMapper">
    <select id="findAll" resultType="User">
        SELECT * from `t_user_info`
    </select>
</mapper>

2.4 不使用MapperScan注解

如果不想使用MapperScan注解来指定dao接口的扫描路径,可以给容器中注入mybatis-spring提供的MapperFactoryBean对象,利用该对象来创建dao层接口的实现类对象,该接口实现了spring的FactoryBean接口,加入该bean到容器时同时会加入一个getObject方法返回的对象到容器中,这样就得到了dao层接口的代理对象

 @Bean
    public MapperFactoryBean<UserMapper> userMapperMapperFactoryBean(SqlSessionFactory sqlSessionFactory) throws Exception {
        MapperFactoryBean<UserMapper> userMapperMapperFactoryBean=new MapperFactoryBean<>();
        userMapperMapperFactoryBean.setMapperInterface(UserMapper.class);
        userMapperMapperFactoryBean.setSqlSessionFactory(sqlSessionFactory);
        return userMapperMapperFactoryBean;
    }

其中的方法参数SqlSessionFactory,spring会自动从容器中获取并注入。

2.5 事务控制

在配置类上加上@EnableTransactionManagement 开启事务支持

在配置类中配置事务管理器的bean

@Bean
    public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource){
        DataSourceTransactionManager dataSourceTransactionManager=new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }

在要控制的方法上加上@Transactional注解

注意使用该注解时,默认情况下只有发生RutimeException系列的异常才会回滚事务,可以通过调整注解的rollbackFor属性来设置发生那种异常回滚事务

@Transactional(rollbackFor = Exception.class)