mybatis源码学习

SqlSessionFactory为一个接口,它的任务是创建SqlSession。SqlSession类似于一个JDBC的Connection对象。

每次应用程序需要访问数据库,我们就要通过SqlSessionFactory创建SqlSession,所以SqlSessionFactory应该在mybatis整个声明周期中。而我们如果多次创建同一个数据库的SqlSessionFactory,则每次创建SqlSessionFactory会打开更多的数据库连接资源,那么连接资源很快就会被耗尽。因此SqlSessionFactory的责任是唯一的,它的责任就是创建SqlSession,所以我们果断采用单例模式。

MyBatis中有两种方式创建SqlSessionFactory:一种是XML配置方式(建议),另一种是代码方式。

提供了两个SqlSessionFactory的实现类,DefaultSqlSessionFactory和 SqlSessionmanager,目前SqlSessionmanager没有使用,mybatis目前使用的是DefaultSqlSessionFactory

public interface SqlSessionFactory {
  SqlSession openSession();
  SqlSession openSession(boolean autoCommit);
  SqlSession openSession(Connection connection);
  SqlSession openSession(TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType);
  SqlSession openSession(ExecutorType execType, boolean autoCommit);
  SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
  SqlSession openSession(ExecutorType execType, Connection connection);
  Configuration getConfiguration();
}

Configuration类的全限定名为:org.apache.ibatis.session.Configuration,它在Mybatis中将以一个Configuration类对象的形式存在,而这个对象将存在于整个Mybatis应用的周期中,以便重复读取和运用。在内存中的数据是计算机系统中读取速度最快的,我们可以解析一次配置的XML文件保存到Configuration类对象中。方便我们从这个对象中读取配置信息,性能高。单例占用空间小,基本不占用存储空间而且可以反复使用。Conf类对象保存着我们配置在Mybatis的信息。

SqlSessionFactoryBuilder为一个类,SqlSessionFactoryBuilder利用XML或者java编码来获得资源来构建SqlSessionFactory的,通过它可以构建多个SqlSessionFactory。它的作用就是一个构建器,一旦我们构建SqlSessionFactory,它的作用就已经完结,失去了存在的意义,这师我们就应该毫不犹豫的废弃它,将它回收。所以它的生命周期只存在于方法的局部,它的作用就是生成SqlSessionFactory对象。

public class SqlSessionFactoryBuilder {

  public SqlSessionFactory build(Reader reader) {
    return build(reader, null, null);
  }

  public SqlSessionFactory build(Reader reader, String environment) {
    return build(reader, environment, null);
  }

  public SqlSessionFactory build(Reader reader, Properties properties) {
    return build(reader, null, properties);
  }

  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(reader, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        reader.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }

  public SqlSessionFactory build(InputStream inputStream) {
    return build(inputStream, null, null);
  }

  public SqlSessionFactory build(InputStream inputStream, String environment) {
    return build(inputStream, environment, null);
  }

  public SqlSessionFactory build(InputStream inputStream, Properties properties) {
    return build(inputStream, null, properties);
  }

  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {
    try {
      XMLConfigBuilder parser = new XMLConfigBuilder(inputStream, environment, properties);
      return build(parser.parse());
    } catch (Exception e) {
      throw ExceptionFactory.wrapException("Error building SqlSession.", e);
    } finally {
      ErrorContext.instance().reset();
      try {
        inputStream.close();
      } catch (IOException e) {
        // Intentionally ignore. Prefer previous error.
      }
    }
  }
    
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }
}
SqlSession是一个接口类(类似于一个JDBC中的Connection接口对象),它类似于你们公司的前台美女客服,它扮演着门面的作用,而真正干活的是 Executor接口,你可以认为它是公司的工程师。假设我是客户找你们公司干活,我只需要告诉前台的美女客服( SqlSession)我们什么信息(参数),要做什么东西,她会将结果给我。在这个过程中,作为用户的我,所关心的是:

(1)要给美女客服(SqlSession)什么信息(功能和参数)

(2)美女客服会给我什么结果(Result)

而我不关系工程师(Executor)是怎么为我工作的,只要前台告诉工程师(Executor),工程师就知道如何为我工作,这个步骤对我而言是个黑箱操作。

SqlSession的用途有两个:(1)获取映射器(2)直接通过命名去执行SQL返回信息(ibatis版本留下的方式)。

SqlSession它的生命周期应该在请求数据库处理事务的过程中。它是一个线程不安全的对象,在涉及多线程的时候我们需要特别的当心,操作数据库需要注意其隔离级别,数据库锁等高级特性。此外,每次创建的SqlSession都必须及时关闭它,它长期存在就会使数据库连接池的活动资源减少,对系统性能的影响很大。

public interface SqlSession extends Closeable {
  <T> T selectOne(String statement);
  <T> T selectOne(String statement, Object parameter);
  <E> List<E> selectList(String statement);
  <E> List<E> selectList(String statement, Object parameter);
  <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds);
  <K, V> Map<K, V> selectMap(String statement, String mapKey);
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey);
  <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds);
  void select(String statement, Object parameter, ResultHandler handler);
  void select(String statement, ResultHandler handler);
  void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler);
  int insert(String statement);
  int insert(String statement, Object parameter);
  int update(String statement);
  int update(String statement, Object parameter);
  int delete(String statement);
  int delete(String statement, Object parameter);
  void commit();
  void commit(boolean force);
  void rollback();
  void rollback(boolean force);
  List<BatchResult> flushStatements();
  void close();
  void clearCache();
  <T> T getMapper(Class<T> type);
  Connection getConnection();
}
Mapper, Mapper是一个接口,而没有任何实现类,它的作用是发送SQL,然后返回我们需要的结果,或者执行SQL从而修改数据库的数据,因此它应该在一个SqlSession事务方法之内,是一个方法级别的东西。它就如同JDBC中一条SQL语句的执行,它的最大范围和SqlSession是相同的。尽管我们一直保存着Mapper,但是你会发现它很难控制,所以尽量在一个SqlSession事务的方法中使用它们,然后废弃掉。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值