Mybatis源码分析-SqlSession

前面我们已经对Mybatis组件有了宏观的认识,并且有提到SqlSession会话使用了门面模式,这里我们先提出两个问题:
1、SqlSession门面模式,方便在了哪里?
2、SqlSession门面带来的方便,Mybatis是否满意了呢?

默认实现DefaultSqlSession#selectList源码

  //statement  Mapper接口方法的全限定名
  //parameter SQL参数
  //rowBounds 分页参数
  public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) {
    try {
      //MappedStatement对应xml中的一个语句,如select、update、delete
      MappedStatement ms = configuration.getMappedStatement(statement);
      //调用Executor执行器处理
      return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER);
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error querying database.  Cause: " + e, e);
    } finally {
      ErrorContext.instance().reset();
    }
  }

从代码可以看出,SqlSession就像是一个接待者,对于接收到的请求,最终都会丢给Executor执行器来处理。SqlSession和Executor的关系是一对一

Executor查询接口

Executor接口.png

从上图可以看出,对于查询操作,Executor只提供了最基础的2种api:返回List列表<E>和返回游标Cursor

SqlSession查询接口

SqlSession查询接口.png

可以看到SqlSession对于查询,提供了更加丰富的api,selectOne、selectMap等,方便了用户调用

SqlSession和Executor使用对比

public class SqlSessionTest {

    private SqlSession sqlSession;
    private Configuration configuration;

    @Before
    public void init(){
        SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
        SqlSessionFactory factory = sqlSessionFactoryBuilder.build(this.getClass().getResourceAsStream("/mybatis-config.xml"));
        sqlSession = factory.openSession();
        configuration = factory.getConfiguration();
    }

    @Test
    public void testSqlSession() throws SQLException {

        //使用Executor查询id=10的User  这里实例化的是重用执行器
        Executor executor = configuration.newExecutor(new JdbcTransaction(sqlSession.getConnection()), ExecutorType.REUSE);
        //传入查询方法的全限定名,获得MappedStatement对象
        MappedStatement mappedStatement = configuration.getMappedStatement("org.coderead.mybatis.UserMapper.selectByid");
        List<User> list = executor.query(mappedStatement, 10, RowBounds.DEFAULT, Executor.NO_RESULT_HANDLER);
        //需要自己对结果进行get0
        User user0 = list.get(0);
        System.out.println(user0);

        //使用SqlSession提供的selectOne查询id=10的User  直接得到User  需要传入查询方法的全限定名
        User user1 = sqlSession.selectOne("org.coderead.mybatis.UserMapper.selectByid", 10);
        System.out.println(user1);

        //使用getMapper得到UserMapper动态代理对象,不需要传入全限定名,调用更加方便
        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
        User user2 = userMapper.selectByid(10);
        System.out.println(user2);
    }
}

可以看出,使用SqlSession提供的selectOne接口,精简了调用参数和返回结果。但是这还不是最满意的效果,SqlSession提供了getMapper接口得到动态代理对象,这样我们就可以直接调用接口方法,更加方便了我们的使用。
而在spring和mybatis整合后,SqlSession也被透明化了,我们都是直接使用接口代理对象,用户对SqlSession,甚至Mybatis的任何类都完全无感。

Sqlsession总结

  • 透明化了Executor的具体实现,用户不用关心是哪一个Executor执行SQL
  • 提供更加丰富的api,selectOne,selectMap
  • 调用接口需要传入方法全限定名,容易出错,因此进一步提供了getMapper方法得到接口的代理实现,直接调用接口方法
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容