美文网首页框架源码研究
抽象-从JDBC到MyBatis

抽象-从JDBC到MyBatis

作者: 无醉_1866 | 来源:发表于2019-10-05 19:44 被阅读0次

JDBC的使用

JDBC的使用方式相对比较繁琐:


  public Object queryUser(int userId) throws SQLException {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet rs = null;
    try {
      connection = dataSource.getConnection();
      preparedStatement = connection.prepareStatement("select id, name from user where id = ?");
      preparedStatement.setInt(1, userId);
      rs = preparedStatement.executeQuery();

      while (rs.next()) {
        final int id = rs.getInt("id");
        final String name = rs.getString("name");
        final User user = new User();
        user.setId(id);
        user.setName(name);
        return user;
      }
      return null;
    } finally {
      close(connection, preparedStatement, rs);
    }
  }

  private void close(Connection connection, PreparedStatement preparedStatement, ResultSet rs) {
    if (rs != null) {
      try {
        rs.close();
      } catch (SQLException e) {
      }
    }
    if (preparedStatement != null) {
      try {
        preparedStatement.close();
      } catch (SQLException e) {
      }
    }
    if (connection != null) {
      try {
        connection.close();
      } catch (SQLException e) {
      }
    }
  }
  

我们再定义两个类:

public class MyMappedStatement {

  private String sql;

  private List<Object> params;

  public String getSql() {
    return sql;
  }

  public void setSql(String sql) {
    this.sql = sql;
  }

  public List<Object> getParams() {
    return params;
  }

  public void setParams(List<Object> params) {
    this.params = params;
  }
}
public class ResultMap {

  Object map(ResultSet rs) {
    //省略
  }
}

查询代码变成如下方式,实现了通用的查询:


 public Object query(MyMappedStatement statement, MyResultMap resultMap) throws SQLException {
    Connection connection = null;
    PreparedStatement preparedStatement = null;
    ResultSet rs = null;
    try {
      connection = dataSource.getConnection();
      preparedStatement = connection.prepareStatement(statement.getSql());

      for (int i = 0; i < statement.getParams().size(); i++) {
        Object p = statement.getParams().get(i);
        preparedStatement.setObject(i + 1, p);
      }

      rs = preparedStatement.executeQuery();

      return resultMap.map(rs);
    } finally {
      close(connection, preparedStatement, rs);
    }
  }

JDBC使用步骤

从上面可以看到,jdbc的使用步骤如下:

  • 获取connection
  • 创建PrespareStatement并绑定参数
  • 执行查询/更新
  • 执行结果集的映射
  • 关闭资源

MyBatis的查询处理

核心概念

  • MappedStatement:表示一条SQL,在xml中写的<select>/<update>或者注解写的@Select/@Update等都会在配置解析后转换成一个MappedStatement对象
  • ResultMap:表示结果集到对象的映射,xml中写的<resultMap>或者注解写的@Results会转换成一个ResultMap
  • Executor:MappedStatement的执行入口

领域模型划分

  • 实体域:MappedStatement/ResultMap/Executor
  • 服务域:Configuration(配置类)

处理步骤

MyBatis框架中封装的处理步骤大体上和前面使用JDBC是一样的,只是mybatis使用了更加抽象的方式:

image.png

从DefaultSqlSession类的selectList方法我们可以看到Executor的调用:


image.png

按上图的流程进去,会非常清晰的看明白整个处理过程,

创建核心处理类的过程

mybatis通过Configuration创建Executor, StatementHandler, ParameterHandler, ResultSetHandler, ResultHandler等对象,Configuration对象是配置解析之后表示 所有配置的对象,我们以Executor为例看看上述对象的创建过程:


image.png

代码中有一行interceptorChain.pluginAll(executor),其作用是利用mybatis的插件创建代理对象,用于拦截核心流程:


image.png

开发的mybatis插件就是通过这段代码应用在指定对象上的

mybatis插件开发见:https://mybatis.org/mybatis-3/configuration.html#plugins

相关文章

网友评论

    本文标题:抽象-从JDBC到MyBatis

    本文链接:https://www.haomeiwen.com/subject/ukhypctx.html