Mybatis:SqlSession的意义

环境:Mybatis 3.5.1

简单理解SqlSession,就是一次操作数据库的会话过程,通过它可以与数据库进行交互

使用Mybatis执行数据库操作,首先要获取SqlSession,通过它进一步获取Mapper接口代理对象,最后通过代理对象发起数据库操作

这是使用Mybatis进行数据库操作的一个Demo,通过构建DataSourceTransactionFactoryEnvironmentConfiguration并将它们组装在一起获得SqlSessionFactory,此后就可以通过它获取SqlSession

public class MybatisDemo {

    public static void main(String[] args) {
        SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
        // 获取SqlSession
        try (SqlSession session = sqlSessionFactory.openSession()) {
            BlogMapper blogMapper = session.getMapper(BlogMapper.class);
            blogMapper.selectBlog(1);
        }
    }

    /**
     * 获取数据源
     */
    private static DataSource getDataSource() {
        Properties properties = new Properties();
        properties.setProperty("driver", "com.mysql.jdbc.Driver");
        properties.setProperty("url", 
                "jdbc:mysql://localhost:3306/study?characterEncoding=UTF8");
        properties.setProperty("username", "root");
        properties.setProperty("password", "123456");
        PooledDataSourceFactory pooledDataSourceFactory 
                = new PooledDataSourceFactory();
        pooledDataSourceFactory.setProperties(properties);
        return pooledDataSourceFactory.getDataSource();
    }

    /**
     * 获取Mybatis的SessionFactory
     */
    private static SqlSessionFactory getSqlSessionFactory() {
        DataSource dataSource = getDataSource();
        TransactionFactory transactionFactory = new JdbcTransactionFactory();
        Environment environment 
                = new Environment("development", transactionFactory, dataSource);
        Configuration configuration = new Configuration(environment);
        configuration.addMapper(BlogMapper.class);
        return new SqlSessionFactoryBuilder().build(configuration);
    }
}

为什么要先获取SqlSession,Mybatis通过它做了什么?

从try-with-resource里的openSession方法,可以定位到DefaultSqlSessionFactory#openSession,在这里可以看到获取SqlSession时Mybatis会创建事务工厂TransactionFactory、执行器Executor结合在启动Mybatis时创建的Configuration返回一个DefaultSqlSession

public class DefaultSqlSessionFactory implements SqlSessionFactory {

    public SqlSession openSession(boolean autoCommit) {
        return openSessionFromDataSource(
                configuration.getDefaultExecutorType(), null, autoCommit);
   }

    private SqlSession openSessionFromDataSource(ExecutorType execType, 
            TransactionIsolationLevel level, boolean autoCommit) {

        Transaction tx = null;
        try {
            final Environment environment = configuration.getEnvironment();

            final TransactionFactory transactionFactory 
                    = getTransactionFactoryFromEnvironment(environment);

            tx = transactionFactory.newTransaction(environment.getDataSource(),
                     level, autoCommit);
            // 为当前会话创建执行器Executor
            final Executor executor = configuration.newExecutor(tx, execType);
            return new DefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx); // may have fetched a connection so lets call close()
        } finally {
        }
    }
}

其中Mybatis利用执行器Executor执行数据库操作,它在获取SqlSession时通过Configuration#newExecutor被创建出来

Executor的创建应用了装饰者模式,如下所示,若开启二级缓存(默认是开启的)会使用CachingExecutor增强其他的Executor,同时在创建Executor之后对其进行了一次拦截器调用

public class Configuration {

    protected boolean cacheEnabled = true;  // 默认启用二级缓存

    public Executor newExecutor(Transaction transaction, ExecutorType executorType) {
        executorType = executorType == null ? defaultExecutorType : executorType;
        executorType = executorType == null ? ExecutorType.SIMPLE : executorType;
        Executor executor;
        if (ExecutorType.BATCH == executorType) {
            executor = new BatchExecutor(this, transaction);
        } else if (ExecutorType.REUSE == executorType) {
            executor = new ReuseExecutor(this, transaction);
        } else {
            executor = new SimpleExecutor(this, transaction);
        }
        if (cacheEnabled) {
            executor = new CachingExecutor(executor);  // 装饰器模式
        }
        executor = (Executor) interceptorChain.pluginAll(executor);  // 应用拦截器
        return executor;
    }
}

至此,Mybatis获取SqlSession的过程结束,通过它为当前的数据库操作创建一个专属的执行器Executor和事务工厂TransactionFactory,令当前线程的数据库操作处于一个会话状态

你可能感兴趣的:(Mybatis:SqlSession的意义)