整体介绍
◆JDBC快速入门
◆精讲JDBC开发细节
◆连接池与DBC进阶使用
主要知识点
◆JDBC使用步骤
◆数据库查询方法
◆数据库写入方法
◆SQL注入攻击的应对
◆连接池的使用
Apache Commons DBUtils
JDBC快速入门
什么是JDBC
◆Java数据库连接-Java DataBase Connectivity
◆JDBC可让Java通过程序操作关系型数据库
◆JDBC基于驱动程序实现与数据库的连接与操作
什么是驱动程序
驱动是每个厂商自己提供的,主要主板内安装了相应驱动,才能识别usb口插入的是什么设备
为啥我们插上设备就能用,没有安装驱动,那是windows内置了很多常见设备的驱动,不用我们自己安装,当使用高级设备如具备宏命令的鼠标时,就需要在相应的官网安装下载相应驱动了
JDBC驱动程序
JAVA无法为每种数据库提供对应的接口,只能提供统一接口JDBC,让每种数据库使用对应的厂商驱动即jar包进行对接访问,JDBC就能通过这个驱动识别数据库并对其访问操作了平台提供标准,厂商提供实现
JDBC的优点
◆统一的API,提供一致的开发过程
◆易于学习,容易上手,代码结构稳定
◆功能强大,执行效率高,可处理海量数据
快速上手JDBC
JDBC开发流程
1.加载并注册JDBC驱动
2.创建数据库连接
3.创建Statement对象
4.遍历查询结果
5.关闭连接,释放资源
准备:在mysql的HL连接下新建imooc数据库,或者导入imooc.sql文件
新建java类项目文件
浏览器搜索”所需驱动名“+ driver ,在各个厂商官网即可找到驱动
mysql jar
创建lib文件夹,将mysql的驱动jar包复制粘贴进去
在工程结构中,选择模块→依赖→’+‘号→JAR
1.加载并注册JDBC驱动
- 创建数据库连接
- 创建Statement对象
- 遍历查询结果
- 关闭连接,释放资源
注意:此处我的数据库的密码为空,所以设置如下:
创建数据库连接代码
Class.forName的作用
◆Class.forName用于加载指定的JDBC驱动类
◆Class.forName本质是通知JDBC注册这个驱动类
◆驱动由数据库厂商自行开发,连接字符串也不同
数据库存储非常重要,一般需要采购服务器进行存储,所以有对应ip和端口号,所以通过连接字符串进行表达
数据库与连接字符串
数据库连接配置
DriverManager
◆DriverManager用于注册/管理JDBC驱动程序
◆DriverManager.getConnection(连接字符串,用户名,密码)
◆返回值Connection对象,对应数据库的物理网络连接
Connection对象
◆Connection对象用于DBC与数据库的网络通信对象
◆java.sql.Connection是一个接口,具体由驱动厂商实现
◆所有数据库的操作都建立在Connection基础上
可以不只建立一个connection对象连接数据库服务器
形成连接池,当JDBC连接服务器如何知道ip和端号以及哪个数据库?
这时需要连接字符串
MySQL连接字符串
◆格式:jdbc:mysql:/[主机ip][:端口]/数据库名?参数列表
◆主机ip与端口是可选设置,默认值为127.0.0.1与3306
◆参数列表采用u编码,格式:参数1=值1&参数2=值2&…
常用参数
局域网开发可以将useSSL设置为false,部署上线时最好设置为true
若工作时发现字符串没有包含其中某些字段,可能说明服务器端已经默认设置好了
创建connection和异常处理
allowPublicKeyRetrieval=true
表示允许从客户端获取公钥加密传输,在生产开发环境中可以设置user为root,但是生产部署中不要对外开放root,因为权限太大,一旦密码泄露,后果不堪设想
记得选中JDBC五步骤,点击code→surround with→try/catch可以自动捕获异常
实现按部门查询员工功能
使用接口进行封装,新建Command.java接口
新建HumanResourceApplication.java文件,是app功能
新建QueryCommand.java文件,实现查询功能,实现上面的接口
rs里面有一系列针对字段的方法,根据字段的数据类型进行选择
JDBC中字段索引从1开始,而非0
代码有非常严重的内存泄露风险,导致可以进行sql注入攻击
SQL注入攻击
输入特殊格式字符从而嵌入到原有sql中破环原有sql筛选条件导致数据破坏泄露的攻击方式称之为sql注入攻击
根本原因是我们没有考虑处理单引号这样的特殊字符
PreparedStatement预编译SQL
用以解决sql注入攻击问题
SQL注入
◆SQL注入攻击是指利用SQL漏洞越权获取数据的黑客行为
◆SQL注入攻击根源是未对原始SQL中的敏感字符做特殊处理
解决方法:放弃Statement改用PreparedStatement处理SQL
PreparedStatement
◆PreparedStatement预编译Statement是Statement的子接口
◆PreparedStatement对SQL进行参数化,预防SQL注入攻击
◆PreparedStatement比Statement执行效率更高
使用PreparedStatement
符号会进行转义处理
使用?占位,setString、setInt传入输入信息
JDBC实现写数据
新增、修改、删除数据
封装DbUtils工具类
将JDBC的重复五个步骤封装
实现打开和关闭两个接口
在文件下新建common文件夹,新增DbUtils。java类
实行封装,抛出异常:
JDBC实现新增数据
JDBC执行INSERT语句
所有写操作都要使用execute.Update方法,而且不返回结果集,而是整数,表示写操作所影响行数
使用DbUtils封装工具类来实现新增数据操作
调用封装的接口conn = DbUtils.getConnection();
,表示打开JDBC连接mysql数据库,使用四个?
进行占位,然后后面使用一系列set方法传入值,最后记得调用关闭接口进行资源释放DbUtils.closeConnection(null,pstmt,conn);
,没有生成结果集,所以使用null
实现了第二个APP的功能:
JDBC实现更新与删除数据
JDBC执行UPDATE语句
JDBC执行DELETE语句
此处cnt的值为0或1,0为不存在,1为存在删除
更新操作:
删除操作:
APP的增删查改功能
JDBC中的事务操作
什么是事务
◆事务是以一种可靠的、一致的方式,访问和操作数据库的程序单元
◆说人话:要么把事情做完,要么什么都不做,不要做一半
◆事务依赖于数据库实现,MySQL通过事务区作为数据缓冲地带
事务的提交操作
案例:韩梅梅向李雷借了100元,韩梅梅余额加100,李雷余额减100,这是一个完整事务,我们不需要两次写入到数据表,我们可以不先更新到数据表,而更新到事务区,等到韩梅梅与李雷的数据全部修改后,再一次性写入到数据表,然后事务区清空,等待下一次事务
事物的回滚操作
回滚后不会对数据表产生任何影响
JDBC两种事务模式
◆JDBC允许两种事务模式
◆自动提交事务模式
◆手动提交事务模式
自动提交事务模式
◆自动提交模式是指每执行一次写操作SQL,自动提交事务
◆自动提交开启方法:conn.setAutoCommit(true)
◆自动事务是DBC默认行为,此模式无法保证多数据一致性
手动提交事务模式
◆手动提交模式是指显式调用commit0与rollback()方法管理事务
◆手动提交开启方法:conn.setAutoCommit(false)
◆手动提交事务可保证多数据一致性,但必须手动调用提交/回滚方法
我们想要插入1000条员工数据,当执行到1005时会产生异常,这时我们想要撤回已经写入的5条数据并修改后重新再次提交到数据表,他是无法完成的,导致数据不完整,不因为是默认自动提交,所以我们需要使用事务控制
这时我们需要关闭自动提交,执行executeUpdate时,就会提交到事务区
,需要自己手动提交,出现异常,自动回滚
如果插入失败后,一条数据也不会写入到数据表中,必须全部成功才会写入数据表中
基于实体类实现分页数据封装
数据的处理不单是打印到屏幕这们简单,在日常开发中,通常将数据转化成一个个实体封装在集合中,即使结果集关闭,也不会影响到我们封装的数据,而且是通过面向对象的方法进行存储,后期更容易被我们的JAVA进行处理
员工实体类构造方法:
通常属性与mysql字段一致
进行分页查询操作:
新建PaginationCommond.java文件,类似上面的增删查改方式,实现Commond的接口
每页10条数据,依托mysql独有方言特殊关键字limit,?表示从第几行开始,后面数字表示截取后面的几行记录
注意mysql页数索引从0开始
JDBC中Date日期对象处理
新增字段hiredate字段,默认date类型,保持到日期的天数
注意选择为java.util下的包
JDBC批处理
tc1()是新增100000个对象,每个对象新增1个数据
tc2()是创建一个对象,新增100000条数据
tc1()创建10万个prepareStatement(sql)
,而tc2()只需创建一个,发送一条sql语句,覆盖10万个参数,再由mysql一次性进行批处理,相反tc1()需要发送10万条sql语句,每一条都相同。浪费了时间
连接池和JDBC的进阶使用
连接池类似生活中的物资仓库,每使用一次mysql就要创建一个JDBC的连接,耗费时间,将连接预算放入连接池,直接在连接池提取使用即可,用完可以还到连接池,继续分配他人使用
阿里巴巴Druid连接池
◆Duid是阿里巴巴开源连接池组件是最好的连接池之一
◆Duid对数据库连接进行有效管理与重用,最大化程序执行效率
◆连接池负责创建管理连接,程序只负责取用与归还
JDBC程序一假设为负责数据的新增,JDBC程序二假设负责数据的查找,都需要与数据库建立连接,耗费时间,我们需要建立一个连接池,让JDBC与连接池通信即可,连接池可以在程序启动时创建,也可以在第一个JDBC与连接池通信时创建,其它JDBC分配即可
Druid连接池的配置与使用
alibaba/druid: 阿里云计算平台DataWorks(https://help.aliyun.com/document_detail/137663.html) 团队出品,为监控而生的数据库连接池 (github.com)
类似mysql的jar包导入方法,将druid的jar包导入lib目录
src下创建druid-config.properties进行druid配置,使其具有良好的维护性
initialSize=10
表示连接池创建时默认创建10个连接,maxActive=20
表示如果实际过程不够用,连接池会额外创建10个连接,即最多不大于20个,如果运行过程中达到上限,就会处于等待状态造成阻塞,等待其他使用的程序调用close()方法,将连接池回收
一般将这两个数值设为一致数值,一开始就分配好所有资源,提升性能和管理
执行完成后会全部消失,回收到连接池
新建DruidSample.java文件
配置文件会随着发布到out目录下,所以使用DruidSample.class.getResource("/druid-config.properties").getPath();
获取类路径文件下的文件路径
propertyFile = new URLDecoder().decode(propertyFile, "UTF-8");
是为了容错考虑,防止文件路径中有中文或者空格,使用getpath方法会对路径进行编码,如空格变为%20,decode就是将%20还原成空格
properties.load(new FileInputStream(propertyFile));
需要传入一个文件输入流,所以文件使用new FileInputStream()
进行包裹
Apache Commons DBUtils
◆commons-dbutils是Apache提供的开源JDBC工具类库
◆它是对DBC的简单封装学习成本极低
◆使用commons-dbutils可以极大简化JDBC编码工作量
DbUtils – Download Apache Commons DbUtils
继续类似上面方法将jar包添加到lib文件夹
Apache Commons DBUtils没有结果集用来存储数据,所以使用new BeanListHandler<>(Employee.class)
转换为实体类进行存储,要求必须是属性和字段一一对应的上,‘?’的参数的传递使用new Object[]{10}
表示从第十行开始截取,{}中的数值对应’?‘里要传入的数值,使用集合进行接收,使用 for (Employee emp : list)
进行遍历后可以打印或者后续处理
注意,在执行query方法的时候,Apache Commons DBUtils会自动连接连接池,执行完后会自动关闭,不需要我们手动打开和关闭
所以利用Apache DbUtils大幅简化了数据的提取过程
然而在执行非query查询方法的时候,如update更新方法,就需要自己创建与数据库的连接,update不止用于更新操作,加入删除等写操作都须使用update方法