前言

上文讲的MyBatis部署运行且根据官网运行了一个demo:一步到位部署运行MyBatis3源码<保姆级>

jdbc

再贴一个JDBC运行的测试方法,流程为:

  • 加载JDBC驱动;
  • 获取数据库连接;
  • 创建JDBC Statements对象;
  • 设置SQL语句的传入参数;
  • 执行SQL语句并获得查询结果;
  • 对查询结果进行转换处理并将处理结果返回;
  • 释放相关资源(关闭Connection,关闭Statement,关闭ResultSet);
    @Test
    public void jdbcTest(){
        String driver = "com.mysql.cj.jdbc.Driver";
        String url = "jdbc:mysql://localhost:3306/news?characterEncoding=utf8&serverTimezone=Asia/Shanghai&useSSL=false&allowPublicKeyRetrieval=true";
        String user = "root";
        String pwd = "root123456";
        Connection connection=null;
        ResultSet rs=null;
        PreparedStatement stmt=null;
        try {
            Class.forName(driver);
            //获取数据库连接
            connection = DriverManager.getConnection(url,user,pwd);
            String sql = "select * from t_level where name=?";
            //创建Statement对象(每一个Statement为一次数据库执行请求)
            stmt=connection.prepareStatement(sql);
            //设置传入参数
            stmt.setString(1,"zhangsan");
            //执行SQL语句
            rs = stmt.executeQuery(sql);
            ResultSetMetaData metaData =rs.getMetaData();
            //处理查询结果-----此处未做操作
            int columnCount= metaData.getColumnCount();
            System.out.println(columnCount);
        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            try{
                //关闭结果集
                if(rs!=null){
                    rs.close();
                    rs=null;
                }
                //关闭执行
                if(stmt!=null){
                    stmt.close();
                    stmt=null;
                }
                if(connection!=null){
                    connection.close();
                    connection=null;
                }
            }catch(SQLException e){
                e.printStackTrace();
            }
        }
    }

传统JDBC弊端

  • JDBC 底层没有用连接池,操作数据库需要频繁的创建和关闭连接,消耗很大的资源;
  • 原生的 JDBC 代码在 Java 中,一旦需要修改 SQL,Java 需要整体编译,不利于系统维护;
  • 使用 PreparedStatement 预编译的话,对变量进行设置 1、2、3 等数字,这样的序号不利于维护;
  • 返回 result 结果集也需要硬编码。

思考

拿JDBC测试用例和上文mybatis的测试用例对比,可以发现哪些些共同点?

    @Test
    public void test() throws IOException {
        InputStream input = Resources.getResourceAsStream("SqlSessionConfig.xml");
        SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(input);
        SqlSession sqlSession = sessionFactory.openSession();
        LevelDao dao = sqlSession.getMapper(LevelDao.class);
        List<Level> all = dao.findAll();
    }

首先他们都要有数据源,这是毋庸置疑的。其次还要有执行sql语句,再有就是执行操作。

源码分析

接下来进入到源码分析阶段。

由于我们是根据官网 Building SqlSessionFactory from XML的方式来测试demo的,接下来我们的解析就按照XML文件配置形式来讲解。

获取数据源

数据源4大元素包括:驱动、 url、 用户名、 密码。

在看代码之前,先看一下我们的配置文件结构。

mybatis是什么时候获取到数据源的呢?要从测试方法生成SqlSessionFactory说起。

通过断点进入到SqlSessionFactoryBuilderbuild方法中,方法体就两行关键代码,首先new了一个XML 配置生成器,接着调用了其parse()生成一个Configuration对象。

  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) {
      }
    }
  }
  public SqlSessionFactory build(Configuration config) {
    return new DefaultSqlSessionFactory(config);
  }

parse方法执行了下面这条语句:

parseConfiguration(parser.evalNode("/configuration"));

parser.evalNode会生成一个mybatis封装的XNode对象,copy后发现就是我们配置文件中<configuration>标签中的内容。

进入到parseConfiguration方法中,可以看出好多方法的字符串参数都和我们<configuration>标签中的一些标签名称相同。没错,每一步都是去扫描到对应参数的标签内容从而进行一些配置处理。

  private void parseConfiguration(XNode root) {
    try {
      //issue #117 read properties first
      propertiesElement(root.evalNode("properties"));
      Properties settings = settingsAsProperties(root.evalNode("settings"));
      loadCustomVfs(settings);
      loadCustomLogImpl(settings);
      typeAliasesElement(root.evalNode("typeAliases"));
      pluginElement(root.evalNode("plugins"));
      objectFactoryElement(root.evalNode("objectFactory"));
      objectWrapperFactoryElement(root.evalNode("objectWrapperFactory"));
      reflectorFactoryElement(root.evalNode("reflectorFactory"));
      settingsElement(settings);
      // read it after objectFactory and objectWrapperFactory issue #631
      environmentsElement(root.evalNode("environments"));
      databaseIdProviderElement(root.evalNode("databaseIdProvider"));
      typeHandlerElement(root.evalNode("typeHandlers"));
      mapperElement(root.evalNode("mappers"));
    } catch (Exception e) {
      throw new BuilderException("Error parsing SQL Mapper Configuration. Cause: "   e, e);
    }
  }

我们此处不研究其他处内容,直接看environmentsElement方法的内容。root.evalNode("environments")返回的XNode对象的value就是我们的environments标签内容。

进入到environmentsElement方法中,会循环遍历下一级的environment,此处便是解析xml配置多数据源的地方。

  private void environmentsElement(XNode context) throws Exception {
    if (context != null) {
      if (environment == null) {
        environment = context.getStringAttribute("default");
      }
      //xml配置多数据源
      for (XNode child : context.getChildren()) {
        String id = child.getStringAttribute("id");
        if (isSpecifiedEnvironment(id)) {
          TransactionFactory txFactory = transactionManagerElement(child.evalNode("transactionManager"));
          //<dataSource></dataSource>
          DataSourceFactory dsFactory = dataSourceElement(child.evalNode("dataSource"));
          //获得到数据库源
          DataSource dataSource = dsFactory.getDataSource();
          Environment.Builder environmentBuilder = new Environment.Builder(id)
              .transactionFactory(txFactory)
              .dataSource(dataSource);
          configuration.setEnvironment(environmentBuilder.build());
        }
      }
    }
  }

dataSourceElement方法会拿到dataSource标签的内容生成一个DataSourceFactory ,并根据我们的配置给其属性赋值。

通过getDataSource()方法便可以拿到我们的数据源。

最后调用configuration.setEnvironment给到全局配置中的。

执行流程图如下:

总结

到此这篇关于MyBatis3源码解析之如何获取数据源的文章就介绍到这了,更多相关MyBatis3获取数据源内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

MyBatis3源码解析之如何获取数据源详解的更多相关文章

  1. HTML实现代码雨源码及效果示例

    这篇文章主要介绍了HTML实现代码雨源码及效果示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  2. 源码推荐:简化Swift编写的iOS动画,iOS Material Design库

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  3. swift皮筋弹动发射飞机ios源码

    这是一个款采用swift实现的皮筋弹动发射飞机游戏源码,游戏源码比较详细,大家可以研究学习一下吧。

  4. swift 写的app 源码,保存一下下

    http://www.topthink.com/topic/3345.htmlhttp://www.csdn.net/article/2015-01-09/2823502-swift-open-source-libs

  5. swift 源码网站 code4app

    http://code4app.com/ios/HTHorizontalSelectionList/54cb2c94933bf0883a8b4583http://123.th7.cn/code/DMPagerViewController_2522.html

  6. OpenStack Swift源码导读:业务整体架构和Proxy进程

    OpenStack的源码分析在网上已经非常多了,针对各个部分的解读亦是非常详尽。其中proxy是前端的业务接入进程。account、container和object目录分别是账户、容器和对象的业务处理逻辑进程。各个业务进程或模块之间的逻辑关系可以参考《OpenstackSwift简介》文中的架构图。在《OpenstackSwift简介》从理论上面介绍了具体的节点寻找过程。

  7. 源码推荐(7.21):顶部滑动菜单FDSlideBar,Swift版无限循环轮播图

    顶部滑动菜单FDSlideBarFDSlideBar是一个顶部滑动菜单,如常见的网易、腾讯新闻等样式。菜单间切换流畅,具有较好的体验性。测试环境:Xcode6.2,iOS6.0以上Swift版无限循环轮播图无限循环轮播图片点击代理可设置图片Url的数组Url和本地图片混合轮播测试环境:Xcode6.2,iOS7.0以上弹幕系统实现--QHDanumuDemo说明:QHDanmu文件夹下是主要的弹幕模块系统,QHDanmuSend文件夹下是简单的发射弹幕的界面。

  8. openstack swift和wsgi源码分析1 HTTP请求处理过程

    分析proxy-server代理服务的执行流程,其他的三个主要服务accountserver,containerserver,objectserver执行过程通proxyserver类似。入口函数调用run_wsgi,此函数完成以下工作:下面重点研究下process_request函数是如何把消息转化为HTTP的request对象这一过程。process_request函数,生成HttpProtocol对象,并执行init操作,注意,HttpProtocol对象自身没有init函数,所以会调用父类的父类的

  9. fir.im Weekly - 进击的 Swift

    最近Swift开源了,众开发者们欢呼雀跃。本期fir.imWeekly准备了一些关于Swift的“新鲜”干货分享,也包括一些优秀的GitHub源码、开发工具和技术文章等等。同时,苹果启用了新的官网:Swift.org,Swift的GitHub主页:https://github.com/apple/swiftSwift3API设计准则勤快的@星夜暮晨翻译了苹果Swift官方网站博客的一篇文章:Swift3APIDesignGuidelines,了解Swift3特性,希望对你有所帮助。如何在iOS中实现一个可

  10. 苹果贴放出Swift语言的源码

    前一段时间苹果贴放出Swift语言的源码,宣布该语言正式开源。其中还包括Swfit核心库项目和全新的Swift包管理器项目。Swift的开源是程序开发者的又一个福音,攻城狮们可以利用SWIFT语言做更多的事情。Swift语言项目的代码分为几个开源库,全部托管在GitHub上。

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部