springboot+mybatis整合配置事务详解(^_^)

springboot集成mybatis有三种方式:

一、最简单的方式就是使用MyBatis官方提供的 mybatis-spring-boot-starter。

二、另一种使用spring-mybatis包的xml配置方式,这样需要自己写一些代码,但可以更灵活的控制mybatis的各项配置。

三、使用引入xml配置(淘汰)

最简单的一(略)太简单就不写了,只要配置数据源即可

这里主要介绍spring-mybatis方式,虽然有些多余,有简单的不用何必要用这种,里面还是有些细节对自己还是很有帮助的。纯粹是个人爱好。

这种方式和一般的用法比较接近。需要添加mybatis依赖和mybatis-spring依赖,然后创建一个MyBatisConfig配置类:

首先配置一个数据源

import org.apache.tomcat.jdbc.pool.DataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DataSourceConfig {

    @Bean 
    public DataSource dataSource(){ 
        DataSource dataSource = new DataSource(); 
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8");
        dataSource.setUsername("test");
        dataSource.setPassword("123456");
        return dataSource;
    }

}

上面的类代表此类为配置类,代表需要注入的bean,使用代码的方式传入值到对象。当然也可以通过application.properties配置文件

@Configuration
@EnableTransactionManagement //开启事务管理
public class MyBatisConfig implements TransactionManagementConfigurer {

    @Autowired
    DataSource dataSource;

    @Bean(name = "sqlSessionFactory")
    public SqlSessionFactory sqlSessionFactoryBean() {
        SqlSessionFactoryBean bean = new SqlSessionFactoryBean();
        bean.setDataSource(dataSource);
        bean.setTypeAliasesPackage("tk.mybatis.springboot.model");

        //分页插件
        PageHelper pageHelper = new PageHelper();
        Properties properties = new Properties();
        properties.setProperty("reasonable", "true");
        properties.setProperty("supportMethodsArguments", "true");
        properties.setProperty("returnPageInfo", "check");
        properties.setProperty("params", "count=countSql");
        pageHelper.setProperties(properties);

        //添加插件
        bean.setPlugins(new Interceptor[]{pageHelper});

        //添加mapper操作数据库XML目录
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
        try {
            bean.setMapperLocations(resolver.getResources("classpath:mapper/*.xml"));
            return bean.getObject();
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
    /*spring通过SqlSessionTemplate对象去操作sqlsession语句*/
    @Bean
    public SqlSessionTemplate sqlSessionTemplate(SqlSessionFactory sqlSessionFactory) {
        return new SqlSessionTemplate(sqlSessionFactory);
    }
    /*配置事务管理器*/
    @Bean
    @Override
    public PlatformTransactionManager annotationDrivenTransactionManager() {
        return new DataSourceTransactionManager(dataSource);
    }
}

上面的配置我们主要通过mybatis的SqlSessionFactoryBean来获取SqlsessionFactory工厂类,通过工厂类获取SqlSessionTemplate对象操作sqlsession语句,值得注意的是SqlSessionTemplate是线程安全的。

在 MyBatis 中,你可以使用 SqlSessionFactory 来创建 SqlSession。一旦你获得一个 session 之后,你可以使用它来执行映射语句,提交或回滚连接,最后,当不再需要它的时 候, 你可以关闭 session。

扫描二维码关注公众号,回复: 6068309 查看本文章

SqlSessionTemplate 是 MyBatis-Spring 的核心。 这个类负责管理 MyBatis 的 SqlSession, 调用 MyBatis 的 SQL 方法, 翻译异常。 SqlSessionTemplate 是线程安全的, 可以被多个 DAO 所共享使用

SqlSessionTemplate 实现了 SqlSession 接口,这就是说,在代码中无需对 MyBatis 的 SqlSession 进行替换。 SqlSessionTemplate 通常是被用来替代默认的 MyBatis 实现的 DefaultSqlSession , 因为模板可以参与到 Spring 的事务中并且被多个注入的映射器类所使 用时也是线程安全的。相同应用程序中两个类之间的转换可能会引起数据一致性的问题。

SqlSessionTemplate 对象可以使用 SqlSessionFactory 作为构造方法的参数来创建。

è¿éåå¾çæè¿°

sqlsessionTemplate构造方法有四个参数:

SqlSessionFactory sessionFactory,

ExecutorType executorType,

PersistenceExceptionTranslator exceptionTranslator

下面纯粹是乱写~~~~

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------

从上面的源码分析,保证线程安全的重点就落在SqlSessionInterceptor()类上了,我们接着找SqlSessionManager又是什么鬼?

è¿éåå¾çæè¿°

你可能会发现SqlSessionManager的构造方法竟然是private的,那我们怎么创建这个对象哪?其实SqlSessionManager创建对象是通过newInstance的方法创建对象的,但需要注意的是他虽然有私有的构造方法,并且提供给我们了一个公有的newInstance方法,但它并不是一个单例模式!

SqlSessionManager的openSession方法及其重载的方法是直接通过调用其中底层封装的SqlSessionFactory对象的openSession方法来创建SqlSession对象的,重载方法如下: 

SqlSessionManager中实现了SqlSession接口中的方法,例如:select、update等,都是直接调用sqlSessionProxy代理对象中相应的方法。在创建该代理对像的时候使用的InvocationHandler对象是SqlSessionInterceptor,他是定义在SqlSessionManager的一个内部类,其定义如下: 

五、总结
综上所述,我们应该大致了解了DefaultSqlSession和SqlSessionManager之间的区别:

1、DefaultSqlSession的内部没有提供像SqlSessionManager一样通过ThreadLocal的方式来保证线程的安全性;

2、SqlSessionManager是通过localSqlSession这个ThreadLocal变量,记录与当前线程绑定的SqlSession对象,供当前线程循环使用,从而避免在同一个线程多次创建SqlSession对象造成的性能损耗;

3、DefaultSqlSession不是线程安全的,我们在进行原生开发的时候,需要每次为一个操作都创建一个SqlSession对象,其性能可想而知;
六、扩展

那么问题来了:

1、为什么mybatis-spring框架中不直接使用线程安全的SqlSessionManager(SqlSessionFactory它是线程安全的)而是使用DefaultSqlSession这个线程不安全的类,并通过动态代理的方式来保证DefaultSqlSession操作的线程安全性哪?

2、DefaultSqlSession中是如何通过Executor来表现策略模式的或者DefaultSqlSession如何使用策略模式模式的?
 

猜你喜欢

转载自blog.csdn.net/jaryle/article/details/87929563