聊聊Spring集成mybatis用到的SqlSessionTemplate

本文探讨了Spring如何使用SqlSessionTemplate集成Mybatis,揭示了MapperFactoryBean的作用和SqlSessionTemplate的线程安全性。同时,文章还介绍了Mybatis的一级缓存和二级缓存机制,并详细解析了#{}和${}的区别,通过源码分析了不同SqlSource的执行过程。
摘要由CSDN通过智能技术生成

一、SqlSessionTemplate的入场

spring在集成mybatis 的时候,并没有使用DefaultSqlSession来一个个getmapper。而是通过@Autowired来直接获取mapper接口,调用mapper方法。那么spring帮助自动注入的mapper到底是什么呢?

其实是一种名为MapperFactoryBean的类,这个类继承了SqlSessionDaoSupport,可以直接获取到SqlSessionTemplate。使用SqlSessionTemplate来代理DefaultSqlSession进行db交互。

那么这个SqlSessionTemplate到底是何方神圣?

SqlSessionTemplate其实是Spring 为了接入mybatis提供的bean,它其实是SqlSession的一个实现类,用于替代DefaultSqlSession的存在,保存线程的SqlSession来保证线程安全性。

既然SqlSessionTemplate是一个Bean,那它默认就是单利的,里面有一个sqlSessionProxy的类变量,他其实是SqlSession的代理类:SqlSessionInterceptor。每次SqlSessionTemplate在执行方法的时候,最后都给交给SqlSessionInterceptor来代理执行,SqlSessionInterceptor每次在获取SqlSession的时候,都会使用事务管理器从threadlocal中获取,所以必然是线程安全的!对于Spring而言,每个事务都会使用同一个SqlSession,其实也就是DefaultSqlSession,用于操作相应的executor来进行db交互。

是不是看到这里有点懵逼?接下来结合源码来进一步分析。

从你依赖注入一个mapper接口到完成一次sql查询的全过程

二、结合源码分析

例:TestMapper.java TestMapper.xml

通过@Autowire来获取一个TestMapper,但其实spring在启动的时候注入的是一个MapperFactoryBean(具体位置在org.mybatis.spring.mapper.ClassPathMapperScanner#processBeanDefinitions中)

下面看看MapperFactoryBean的源码

// 继承了SqlSessionDaoSupport,继承了SqlSessionDaoSupport可以用于直接获取SqlsessionTemplate
public class MapperFactoryBean<T> extends SqlSessionDaoSupport implements FactoryBean<T> {
   

  // 真正的mapper文件
  private Class<T> mapperInterface;

  public MapperFactoryBean() {
   
    //intentionally empty 
  }
  
  public MapperFactoryBean(Class<T> mapperInterface) {
   
    this.mapperInterface = mapperInterface;
  }
  ...
}

再来看看通过SqlSessionDaoSupport获取到的SqlSessionTemplate里面是什么:

  // 其实为defaultSqlSession的代理类SqlSessionInterceptor
  private final SqlSession sqlSessionProxy;
  
  public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,
      PersistenceExceptionTranslator exceptionTranslator) {
   

    notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required");
    notNull(executorType, "Property 'executorType' is required");

    this.sqlSessionFactory = sqlSessionFactory;
    this.executorType = executorType;
    this.exceptionTranslator = exceptionTranslator;
    // jdk动态代理
    this.sqlSessionProxy = (SqlSession) newProxyInstance(
        SqlSessionFactory.class.getClassLoader(),
        new Class[] {
    SqlSession.class },
        new SqlSessionInterceptor());    
  }
  
 ...
   
   // 内部类 SqlSessionInterceptor 
   private class SqlSessionInterceptor implements InvocationHandler {
   
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
   
      // SqlSessionUtils.getSession(...) 是工具类, 里面使用事务同步管理器从threadlocal中获取到SqlsessionHolder, sqlsessionholder可以用于获取缓存了的DefaultSqlSession
      SqlSession sqlSession = getSqlSession(
          SqlSessionTemplate.this.sqlSessionFactory
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值