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、 用户名、 密码。

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

MyBatis3源码解析之怎么获取数据源

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>标签中的内容。

MyBatis3源码解析之怎么获取数据源

MyBatis3源码解析之怎么获取数据源

进入到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标签内容。

MyBatis3源码解析之怎么获取数据源

MyBatis3源码解析之怎么获取数据源

进入到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源码解析之怎么获取数据源”的内容了,经过本文的学习后,相信大家对MyBatis3源码解析之怎么获取数据源这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

文章标题:MyBatis3源码解析之怎么获取数据源,发布者:亿速云,转载请注明出处:https://worktile.com/kb/p/27070

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
亿速云的头像亿速云认证作者
上一篇 2022年9月19日 下午11:56
下一篇 2022年9月19日 下午11:57

相关推荐

  • cad块如何创建

    cad块创建方法: 1、首先打开CAD图纸,然后去绘制一个方格图形。 2、然后在命令栏中输入图块命令“B”按下空格键。 3、然后去选择你要创建的图形,编辑名称后点击确定即可创建。 4、最后只要双击你的鼠标,就可以看到属性了,即可成功创建块。 到此,关于“cad块如何创建”的学习就结束了,希望能够解决…

    2022年8月30日
    39400
  • Redis常见分布锁的原理是什么和怎么实现

    常见的分布式锁的实现如下图: 基于数据库 悲观锁 悲观锁(Pessimistic Lock)顾名思义为很悲观的锁,每次在拿数据的时候都会上锁。这样别人想拿数据就被挡住,直到悲观锁被释放,悲观锁中的共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程,但是在效率方面,处理加锁的机制…

    2022年8月30日
    61100
  • php如何对数组逆向排序且不保留键名

    实现步骤:1、利用array_reverse()函数对数组进行逆向排序,语法“array_reverse(原数组)”,会返回一个逆向数组;2、使用array_values()函数重置逆向数组的键名,语法“array_values(逆向数组)”,被返回的数组将使用数值键,从0开始且以1递增。 本教程操…

    2022年9月18日
    43000
  • vlookup函数精确匹配怎么选择

    vlookup函数精确匹配是1还是0 答:vlookup函数精确匹配是0 1、0代表的是精确匹配,1代表的是模糊匹配。 2、此外,FALSE也可以代表精确匹配,true代表近似匹配。 3、使用精确匹配,就是必须要查找值必须完全匹配,才会导出结果。 4、而模糊匹配有类似值就会匹配到结果中。 5、我们可…

    2022年9月22日
    1.0K00
  • steam人机身份验证captcha无效如何解决

    方法一: 1、使用浏览器打开steam。 2、建议使用谷歌浏览器。 3、在谷歌浏览器中就能通过人机验证了。 方法二: 1、如果在浏览器中也无法解决。 2、可以先将右上角的”语言“改为“英语”再试试看。 方法三: 1、如果还是不行,那么打开防火墙,点击“启用或关闭windows…

    2022年8月30日
    82900
  • thumb文件夹可以删除吗

    thumb指的是系统隐藏缓存文件,可以删除;thumb文件是系统为例提高文件夹在缩略图查看方式下的响应速度而对当前文件夹下的图像文件建立的缓存,可以方便用户对图片进行预览,删除或者禁用都不会对系统造成影响。 本教程操作环境:windows10系统、DELL G3电脑。 thumb是什么文件夹?可以删…

    2022年9月18日
    1.9K00
  • 怎么修改pip install默认安装路径

    1. 修改pip install默认安装路径 一般使用Anaconda时会使用 pip install ### 来安装各类包,但默认安装路径在C盘,极大占用空间,作为强迫症,我们通过以下步骤来修改默认安装路径。 1.1 查看pip 默认安装位置 名列前茅步:通过win菜单,找到Prompt,点击进入…

    2022年8月30日
    3.6K00
  • MySQL中的join语句算法如何优化

    一、join语句算法 创建两个表t1和t2 CREATE TABLE `t2` ( `id` int(11) NOT NULL, `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `a` (`a`)…

    2022年9月16日
    55600
  • 如何使用css实现​文本渐变

    文本渐变 文本渐变效果很流行,使用 CSS3 能够很简单就实现: h3[data-text] { position: relative;}h3[data-text]::after { content: attr(data-text); z-index: 10; color: #e3e3e3; pos…

    2022年9月1日
    35600
  • program files可不可以删除

    “program files”不可以删除;“program files”文件夹是windows系统的程序文件夹,在系统安装完成后就已经生成,该文件夹用于存放已经安装的应用程序,位于C盘根目录,如果删除可能会导致系统运行的不稳定,导致操作系统的崩溃。 本教程操作环境:windows10系统、DELL …

    2022年9月10日
    1.3K00
注册PingCode 在线客服
站长微信
站长微信
电话联系

400-800-1024

工作日9:30-21:00在线

分享本页
返回顶部