浅谈MyBatis的工作原理

了解MyBatis工作原理先了解这几个类的作用:

Configuration           MyBatis所有的配置信息都保存在Configuration对象之中,配置文件中的大部分配置都会存储到该类中

SqlSession               作为MyBatis工作的主要顶层API,表示和数据库交互时的会话,完成必要数据库增删改查功能

Executor                   MyBatis执行器,是MyBatis 调度的核心,负责SQL语句的生成和查询缓存的维护

StatementHandler    封装了JDBC Statement操作,负责对JDBC statement 的操作,如设置参数等

ParameterHandler    负责对用户传递的参数转换成JDBC Statement 所对应的数据类型

ResultSetHandler     负责将JDBC返回的ResultSet结果集对象转换成List类型的集合

TypeHandler             使用Java反射技术完成JavaBean对象到数据库参数之间的相互转换

SqlSource                 负责根据用户传递的parameterObject,动态地生成SQL语句,将信息封装到BoundSql对象中,并返回

BoundSql                  表示动态生成的SQL语句以及相应的参数信息

MyBatis层次结构图:

 

创建SqlSession的工程源码解读:

// 这是一个创建SqlSession的过程

// 将配置文件以流的形式引入
String resource = "mybatis-config.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
// 创建SqlSessionFactory
SqlSessionFactoryBuilder sessionFactory = new SqlSessionFactoryBuilder();
SqlSessionFactory factory = sessionFactory.build(inputStream);
// 创建sqlSession
SqlSession session = factory.openSession();
  • 了解一下SqlSessionFactory创建过程及作用:
/**
 * SqlSessionFactoryBuilder类中只有9个重写的build方法,
 * 我删除了方法体中的内容、
 */

public class SqlSessionFactoryBuilder {

  
  public SqlSessionFactory build(Reader reader) {}

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

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

  public SqlSessionFactory build(Reader reader, String environment, Properties properties) {}

  // 以流的形式将配置文件引入
  public SqlSessionFactory build(InputStream inputStream) {}

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

  public SqlSessionFactory build(InputStream inputStream, Properties properties) {}
  
  // 将主配置文件加载
  public SqlSessionFactory build(InputStream inputStream, String environment, Properties properties) {}
  
  // 将主配置文件引入的其他配置文件加载
  public SqlSessionFactory build(Configuration config) {}

}

 

  • 接下来看一下SqlSession的创建过程:
// SqlSession和核心类Executor挂钩
public DefaultSqlSession(Configuration configuration, Executor executor, boolean autoCommit) {
    this.configuration = configuration;
    this.executor = executor;
    this.dirty = false;
    this.autoCommit = autoCommit;
  }

  public DefaultSqlSession(Configuration configuration, Executor executor) {
    this(configuration, executor, false);
  }
  • SqlSession都是通过Executor来执行的,所以Executor是MyBatis的核心。
  • Executor并没有真正的去执行数据库操作,而是交由StatementHanlder来处理的。
public interface StatementHandler {

	//从Connection中获取Stament对象
	Statement prepare(Connection connection) throws SQLException;
	
	//设置预处理参数
	void parameterize(Statement statement) throws SQLException;
	
	//调用批量操作
	void batch(Statement statement) throws SQLException;
	
	//更新操作
	int update(Statement statement) throws SQLException;
	
	//查询操作
	<E> List<E> query(Statement statement, ResultHandler resultHandler) throws SQLException;
	
	//获取执行SQL语句的封装类BoundSql
	BoundSql getBoundSql();
	
	//参数处理器
	ParameterHandler getParameterHandler();

}
  •  接下来就是使用ParameterHandler来设置参数,getParameterObject()是获取参数的,而setParameters()是设置参数的

        ,相当于对一条sql所有的参数都执行ps.setXXX(value); 

/**
 * A parameter handler sets the parameters of the {@code PreparedStatement}
 *
 * @author Clinton Begin
 */
public interface ParameterHandler {

  Object getParameterObject();

  void setParameters(PreparedStatement ps)
      throws SQLException;

}
  • 从mybatis接收参数到mysql存储数据,都会用到typeHandler类型处理器。这也就是从JavaType->JdbcType的转化过程。由于mybatis初始时已经内置大部分基础类型转化的TypeHandler,已经足够我们平常的简单应用开发了,所以大多数情况下并不需要我们自己去定义类型转换器。
public TypeHandlerRegistry() {
    register(Boolean.class, new BooleanTypeHandler());
    register(boolean.class, new BooleanTypeHandler());
    register(JdbcType.BOOLEAN, new BooleanTypeHandler());
    register(JdbcType.BIT, new BooleanTypeHandler());

    register(Byte.class, new ByteTypeHandler());
    register(byte.class, new ByteTypeHandler());
    register(JdbcType.TINYINT, new ByteTypeHandler());

    register(Short.class, new ShortTypeHandler());
    register(short.class, new ShortTypeHandler());
    register(JdbcType.SMALLINT, new ShortTypeHandler());

    register(Integer.class, new IntegerTypeHandler());
    register(int.class, new IntegerTypeHandler());
    register(JdbcType.INTEGER, new IntegerTypeHandler());

    register(Long.class, new LongTypeHandler());
    register(long.class, new LongTypeHandler());

    .......
}
  • 这样就生成了原生的JDBC操作代码。
  • 再看ResultSetHandler负责的任务:

(1)处理Statement执行后产生的结果集,生成结果列表

(2)处理存储过程执行后的输出参数

/**
 * @author Clinton Begin
 */
public interface ResultSetHandler {

  // 处理执行statement后的结果集
  <E> List<E> handleResultSets(Statement stmt) throws SQLException;

  // 执行存储过程执行后的输出参数
  <E> Cursor<E> handleCursorResultSets(Statement stmt) throws SQLException;

  void handleOutputParameters(CallableStatement cs) throws SQLException;

}

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值