前言
上文讲的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说起。
通过断点进入到SqlSessionFactoryBuilder
的build
方法中,方法体就两行关键代码,首先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
给到全局配置中的。
执行流程图如下:
来源:https://juejin.cn/post/7113036519350206472


猜你喜欢
- 本文实例讲述了winform绑定快捷键的方法。分享给大家供大家参考。具体分析如下:第一种:Alt + *(按钮快捷键)在大家给button、
- 熟悉Android的朋友们都知道,不管是微博客户端还是新闻客户端,都离不开列表组件,可以说列表组件是Android数据展现方面最重要的组件,
- Mybatis是业界非常流行的持久层框架,轻量级、易用,在金融IT领域完全是领军地位,比Hibernate更受欢迎,优势非常多,也是非常值得
- 目录概述代码实现代码地址概述多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。具有多线程能力的计算机因
- 概述AOP(Aspect Orient Programming),我们一般称为面向方面(切面)编程,作为面向对象的一种补充,用于处理系统中分
- 为了防止测试妹子或者用户频繁点击某个按钮,导致程序在短时间内进行多次数据提交or数据处理,那到时候就比较坑了~那么如何有效避免这种情况的发生
- Android Java 如何调用自己的 C++ 的类库下面以 Java 调用 C++ 的加法运算函数为例,做简单说明。(使用 Androi
- 1、python的每一个语句的后面可以添加分号也可以不添加分号;在一行有多条语句的时候,必须使用分号加以区分2、查看Python版本号,在D
- 本文将基于Spring Boot介绍两种生成二维码的实现方式,一种是基于Google开发工具包,另一种是基于Hutool来实现;
- 前言因为最近的项目需要使用录音功能,开始的想法是Button+OnTouchListener+Dialog实现,在大部分手机中都没问题,只有
- 本文实例为大家分享了Java多线程实现第三方数据同步的具体代码,供大家参考,具体内容如下一、场景最近的一项开发任务是同步第三方数据,而第三方
- 前提在Windows下进行数据处理的时候最常见的情况莫过于读取Microsoft的Excel文件了,Excel的普及率惊人,是事实上的标准。
- 一、简述mybatis驼峰式命名规则自动转换:使用前提:数据库表设计按照规范“字段名中各单词使用下划线"_"划分”;使用
- public class LogHelper { &nbs
- CardView介绍CardView是Android 5.0系统引入的控件,相当于FragmentLayout布局控件然后添加圆角及阴影的效
- 本文实例讲述了Java基于分治算法实现的棋盘覆盖问题。分享给大家供大家参考,具体如下:在一个2^k * 2^k个方格组成的棋盘中,有一个方格
- /** * 日期工具类 * 默认使用 "yyyy-MM-dd HH:mm:ss" 格式化日期&nbs
- 有时候我们做Android开发,需要弹一个用户提示,但是有时候设计的提示弹窗是带有图片的,我们每次写一个特别麻烦。所以我特地封装了一个工具类
- BottomBarBottomBar是Github上的一个开源框架,因为从1.3.3开始不支持fragments了,要自己配置,弄了很久,不
- 导语:有些时候我们所需要查询的数据量比较大,但是jvm内存又是有限制的,数据量过大会导致内存溢出。这个时候就可以使用流式查询,数据一条条的返