MyBatis,或者说任何java里的数据库框架底层都是JDBC去连接和操作数据库的,所以在阅读数据库框架之前,需要知道一些JDBC的基础知识,不然你在看源码的时候会感觉很奇怪,这些代码这么写到底是干嘛的?完全不得其意。
废话不多说,接下来进入正题。
JDBC
JDBC,英文是Java Data Base Connectivity(Java数据库连接)。
从名字可以看出,它负责用java语言连接数据库,这个是JDK里面的工具库。
官方文档传送门:JDBC文档
注意它并没有实现跟具体数据库的连接,而只是定义了一种规范,协议,或者说接口,然后各个厂商自己分别去实现,这些实现就是我们常说的驱动包,比如mysql就有自己专门的驱动包,你只有导入才能连数据库。
这里你可能会有疑惑为啥不直接在jdk里面去实现数据库连接呢?而要去定义接口?
主要是数据库种类太多,而且后续可能还会新增。这里运用的设计模式里面桥接模式的思想,直接将具体连接数据库的实现抽象出来,这块在代码里面是Driver,然后我通过Driver去拿到连接操作数据库,具体每个数据库实现各自厂商去实现就好。这样做的好处是充分解耦了数据库驱动和数据库操作的关系。如果我切换另一个数据库只需要改一些配置,然后导入对应的驱动包就行,我的代码是全部不变的。
好了,背景说完了,这时候我们可以了解到在java里面你想要学习数据库相关的框架,JDBC是基础,所有框架都是在JDBC上面封装出来的,那我们今天就来详细的看看JDBC里面都有些啥东西,都是怎么用的?
JDBC组成
主要分为几个大部分:
- Driver(驱动): 数据库驱动抽象,在驱动加持下我们可以直接操作数据库,执行sql,每种数据库会对应一种Driver,比如mysql的Driver,oracle的Driver,sqlserver的Driver等,这些驱动都是交给各个厂商去实现的。
- DataSource: 数据库抽象,代表我们连接的数据库。
- Connect: 连接数据库之后,如果想要执行sql语句,都必须获取Connect,然后再这个Connect之上进行操作,因为连接资源是有限的,当其他连接没有被释放时,你就需要等。
- Statement: sql执行的操作描述抽象,它会包含需要执行的sql语句和一些其他的额外信息。
PreparedStatement
:预编译语句,防止sql注入,将语句的参数用一个个占位符先代替然后填充,现在基本用的这种。CallableStatement
:存储过程调用,现在用的很少了。
ResultSet
:Statement执行结果集,比如select 语句的ResultSet里面就会包含所有的查询结果。
看了这几大组成部分之后,我们也就很容易整理出数据库操作流程了。
- 装载驱动 : 下载对应的数据库jar驱动包
- 获取数据源:加载驱动,然后利用数据库type,用户名,密码等信息连接到具体的数据库实例
- 获取连接:利用数据源获得一个连接
- 组装数据库操作语句:构建Statement。
- 执行操作语句
- 获取结果集:组装到你想要的object。
- 关闭连接。
语句执行API
这里面其实有几个问题,JDBC执行操作语句的API是什么呢?怎么将resultset
转化成想要的javaBean呢?连接的获取每次都需要关闭,是否有更好的方式可以“循环”利用呢?
API主要是statement接口里面的三个execute方法:
execute
:如果第一个结果是结果集则返回为true,否则为false。这个方法主要是查询和修改(这里的更改包括增加和删除)操作的结合体,一般不常用executeQuery
:返回一个结果集对象,主要是查询executeUpdate
:返回该执行语句受影响的行数,当使用插入,删除,更新等操作时会用到,主要是修改,当然表创建和设置用户权限也可以用这个
executeBatch方法
然后数据量很大的时候,比如一次性操作1000W的数据,我们一条条发送请求,整个网络的消耗是十分巨大的,所以jdbc有一种batch操作的方式进行数据库交互,底层其实就是将原本1000W次的数据处理,变成分批发送处理,具体每批大小你可以自己定,这样大大提高了执行效率。这种批处理在jdbc里面对应的是executeBatch()
方法。
resultset
转化
我们实际开发中不会直接用resultset
,因为很难用,它是数据库的字段名或者下标找到具体数据。
而我们想要的是实际的业务javaBean
,这时候就需要将两者进行转化,在以前没有ORM框架之前都是开发人员自己做的,在有了Mybatis
这些ORM框架之后都是直接用框架了,因为简单方便, 当然mybatis
的功能不止这些。
DataSource的不同实现
早期的DataSource拿到的连接都是用完就关闭,这样效率很低,随着后面数据量越来越大,引入了数据库连接池的实现。
为什么要引入数据库连接池?因为连接的建立消耗是十分巨大的,当并发量很大的时候,一个连接其实可以在上个连接用完之后马上给下一个用,这样完全不影响,而不必将上个用完的连接直接关闭,因为下次建立连接又会有很多消耗。于是我们建立了一个池子,每次将用完的连接释放时不是真的释放,而是放到连接池里,下次如果有其他地方要用连接且连接池有空余的话直接拿连接池的就行。