MyBatis工作原理源码分析(二)——获取SqlSession对象

一、引言

由上一篇知,手动使用Mybatis的四个步骤:

获取SqlSessionFactory对象
获取sqlSession对象
获取接口的代理对象(MapperProxy)
执行增删改查方法

上一篇中MyBatis工作原理源码分析(一),详细分析了第一步SqlSessionFactory的初始化过程,下面在此基础上,来分析SqlSession对象的获取。

二、获取SqlSession对象源码分析

当获取到SqlSessionFactory之后,就可以通过SqlSessionFactory去获取SqlSession对象。下面来分析一下源码:

 //2、获取sqlSession对象
 SqlSession openSession = sqlSessionFactory.openSession();

1、调用openSession()方法,获取sqlSession对象

@Override
public SqlSession openSession() {
   //从数据源中拿openSession,参数是得到默认的ExecutorType,默认是Simple,即简单的执行器
  return openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
}

2、调用openSessionFromDataSource()方法

private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) {
    Transaction tx = null;
    try {
      //通过Confuguration对象去获取Mybatis中的Environment对象,该包含了数据源和事务的配置
      final Environment environment = configuration.getEnvironment();
      //获取一些信息,创建事务
      final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
      tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
      
      //从表面上来看,咱们是用sqlSession在执行sql语句, 实际呢,其实是通过excutor执行,excutor是对于Statement的封装
      final Executor executor = configuration.newExecutor(tx, execType);
      //关键在这,创建了一个DefaultSqlSession对象!!!!!!
      return new DefaultSqlSession(configuration, executor, autoCommit);
      
    } catch (Exception e) {
     
    } finally {
      ErrorContext.instance().reset();
    }
  }

3、根据Executor在全局配置中的类型,创建出SimpleExecutor/ReuseExecutor/BatchExecutor

//根据ExecutorType类型,创建一个Executor
public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
   executorType = executorType == null ? defaultExecutorType : executorType;
   executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
   Executor executor;
   if (ExecutorType.BATCH == executorType) {
   	 //创建一个BatchExecutor
     executor = new BatchExecutor(this, transaction);
   } else if (ExecutorType.REUSE == executorType) {
     //创建一个ReuseExecutor
     executor = new ReuseExecutor(this, transaction);
   } else {
     //创建一个SimpleExecutor
     executor = new SimpleExecutor(this, transaction);
   }
   //如果二级缓存如果开启,则创建一个CachingExecutor
   if (cacheEnabled) {
     executor = new CachingExecutor(executor);
   }
   //很重要!很重要!很重要!每一个Executor创建都要走这一步。
   executor = (Executor) interceptorChain.pluginAll(executor);
   //返回包装后的Executor
   return executor;
 }

4、获取到所有拦截器,调用每一个拦截器的plugin方法,重新将executor包装一下

public Object pluginAll(Object target) {
  for (Interceptor interceptor : interceptors) {
    target = interceptor.plugin(target);
  }
  return target;
}

说明:Executor是一个接口,里面有增删改查的方法,源码如下。

public interface Executor {

  ResultHandler NO_RESULT_HANDLER = null;

  int update(MappedStatement ms, Object parameter) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler, CacheKey cacheKey, BoundSql boundSql) throws SQLException;

  <E> List<E> query(MappedStatement ms, Object parameter, RowBounds rowBounds, ResultHandler resultHandler) throws SQLException;

  <E> Cursor<E> queryCursor(MappedStatement ms, Object parameter, RowBounds rowBounds) throws SQLException;

  List<BatchResult> flushStatements() throws SQLException;

  void commit(boolean required) throws SQLException;

  void rollback(boolean required) throws SQLException;

  CacheKey createCacheKey(MappedStatement ms, Object parameterObject, RowBounds rowBounds, BoundSql boundSql);

  boolean isCached(MappedStatement ms, CacheKey key);

  void clearLocalCache();

  void deferLoad(MappedStatement ms, MetaObject resultObject, String property, CacheKey key, Class<?> targetType);

  Transaction getTransaction();

  void close(boolean forceRollback);

  boolean isClosed();

  void setExecutorWrapper(Executor executor);

}

三、小结

下面是上面分析的时序图:

在这里插入图片描述
总结:

1、返回SqlSession的实现类DefaultSqlSession对象,它里面包含了Executor和Configuration;

2、Executor会在这一步被创建,用于执行Sql。

### 回答1: Mybatis获取SqlSession对象方法有两种: 1. 通过SqlSessionFactory获取SqlSession对象 首先需要创建一个SqlSessionFactory对象,可以通过读取mybatis的配置文件来创建,然后通过SqlSessionFactory对象的openSession()方法获取SqlSession对象。 示例代码: //读取mybatis配置文件 InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); //创建SqlSessionFactory对象 SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); //获取SqlSession对象 SqlSession sqlSession = sqlSessionFactory.openSession(); 2. 通过Spring框架获取SqlSession对象 如果项目使用了Spring框架,可以通过Spring的容器来获取SqlSession对象。需要在Spring的配置文件配置SqlSessionFactory和SqlSessionTemplate两个Bean,然后通过@Autowired注解来注入SqlSessionTemplate对象。 示例代码: <!-- 配置SqlSessionFactory --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <!-- 配置SqlSessionTemplate --> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory"/> </bean> //注入SqlSessionTemplate对象 @Autowired private SqlSessionTemplate sqlSessionTemplate; ### 回答2: MyBatis获取SqlSession对象是非常重要的,SqlSessionMyBatis操作数据库的核心对象,用来执行SQL语句、提交事务、获取映射器等。 三种获取SqlSession对象的方式: 1.使用SqlSessionFactoryBuilder来读取配置文件,创建SqlSessionFactory对象,再通过SqlSessionFactory对象创建SqlSession对象: ``` String resource = "mybatis-config.xml"; InputStream inputStream = Resources.getResourceAsStream(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); ``` 2.使用MyBatis提供的Resources类,直接获取配置文件流,创建SqlSessionFactory对象,再通过SqlSessionFactory对象创建SqlSession对象: ``` String resource = "mybatis-config.xml"; Reader reader = Resources.getResourceAsReader(resource); SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(reader); SqlSession sqlSession = sqlSessionFactory.openSession(); ``` 3.使用Spring框架集成MyBatis,通过SqlSessionFactoryBean配置SqlSessionFactory,再通过SqlSessionFactory来创建SqlSession对象: ``` <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/test?useSSL=false"/> <property name="username" value="root"/> <property name="password" value="password"/> </bean> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="configLocation" value="classpath:mybatis-config.xml"/> </bean> <bean id="sqlSession" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg ref="sqlSessionFactory"/> </bean> ``` 无论是哪种方式获取SqlSession对象,都要注意调用close方法SqlSession对象关闭,释放数据库资源。 否则,容易出现数据库连接泄漏的问题,影响系统性能。因此,在使用MyBatis操作数据库时,一定要注意SqlSession的使用和关闭。 ### 回答3: Mybatis是一个基于Java的开源数据访问框架,提供了面向对象的持久化操作方式,是许多Java Web应用的首选框架。其核心是SqlSessionMybatis通过SqlSession与数据库进行交互。因此,获取SqlSession对象是使用Mybatis的第一步。 获取SqlSession对象主要有以下两种方式: 1. SqlSessionFactoryBuilder 首先,需要创建SqlSessionFactoryBuilder对象,通过它配置Mybatis并创建SqlSessionFactory对象,再通过SqlSessionFactory对象生成SqlSession对象。示例代码如下: ``` InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml"); SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder(); SqlSessionFactory sqlSessionFactory = builder.build(inputStream); SqlSession sqlSession = sqlSessionFactory.openSession(); ``` 这里,首先使用Resources.getResourceAsStream加载Mybatis配置文件mybatis-config.xml,然后创建SqlSessionFactoryBuilder对象builder,调用其build方法创建SqlSessionFactory对象sqlSessionFactory,最后通过SqlSessionFactory对象的openSession方法获取SqlSession对象sqlSession。 2. @Inject注解 另外一种获取SqlSession对象的方式是使用@Inject注解。通过在Mapper接口的字段或setter方法上添加@Inject注解,Mybatis会自动注入SqlSession对象。示例代码如下: ``` public interface UserMapper { @Inject SqlSession sqlSession; // 或者 void setSqlSession(SqlSession sqlSession); } ``` 这里,通过@Inject注解,Mybatis会自动注入SqlSession对象sqlSession。另外也可以通过setter方法进行注入。 总结起来,获取SqlSession对象有两种常用方式:通过SqlSessionFactoryBuilder对象创建,或在Mapper接口使用@Inject注解。根据实际情况选择合适的方式进行使用即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

止步前行

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值