JDBC_韩顺平老师转载
- 第25章 JDBC 和数据库连接池
第25章 JDBC 和数据库连接池
JDBC 概述
基本介绍
-
JDBC为访问不同的数据库提供了统一的接口,为使用者屏蔽了细节问题。
-
Java程序员使用JDBC,可以连接任何提供了JDBC驱动程序的数据库系统,从而完成对数据库的各种操作。
-
JDBC的基本原理图[重要!]

模拟JDBC
|
|
|
|
|
|
|
|
JDBC 带来的好处
如果Java直接访问数据库(示意图)

JDBC带来的好处(示意图)
说明:JDBC是Java提供一套用于数据库操作的接口APl, Java程序员只需要面向这套接口编程即可。不同的数据库厂商,需要针对这套接口,提供不同实现。

JDBC API是一系列的接口,它统一和规范了应用程序与数据库的连接、执行SQL语句,并到得到返回结果等各类操作,相关类和接口在java.sql与javax.sql包中


JDBC 快速入门
JDBC 程序编写步骤
- 注册驱动–加载Driver类
- 获取连接–得到Connection(java程序和数据库之间的连接)
- 执行增删改查–发送SQL给mysql执行
- 释放资源–关闭相关连接
JDBC 第一个程序
通过jdbc对表actor 进行添加,删除和修改操作
|
|
获取数据库连接5种方式
方式1
|
|
方式2
|
|
方式3
使用DriverManager 替代 driver 进行统一管理

|
|
方式4
|
|
- mysqL驱动5.1.6 可以无需 CLass . forName(“com.mysql.jdbc.Driver”);
- 从jdk1.5以后使用了jdbc4,不再需要显示调用class.forName()注册驱动而是自动调用驱动jar包下
META-INF\servicesViava.sql.Driver文本中的类名称去注册 - 建议还是写上 CLass . forName(“com.mysql.jdbc.Driver”),更加明确
方式5
|
|
ResultSet[结果集]
基本介绍
- 表示数据库结果集的数据表,通常通过执行查询数据库的语句生成
- ResultSet对象保持一个光标指向其当前的数据行。最初,光标位于第一行之前
- next方法将光标移动到下一行,并且由于在ResultSet对象中没有更多行时返回false,因此可以在while循环中使用循环来遍历结果集
应用实例
|
|

Statement
基本介绍
-
Statement对象用于执行静态SQL语句并返回其生成的结果的对象
-
在连接建立后,需要对数据库进行访问,执行命名或是SQL语句,可以通过
- Statement[存在SQL注入]
- PreparedStatement[预处理]
- CallableStatement[存储过程]
- Statement对象执行SQL语句,存在SQL注入风险。

-
SQL注入是利用某些系统没有对用户输入的数据进行充分的检查,而在用户输入数据中注入非法的SQL语句段或命令,恶意攻击数据库。
-
要防范SQL注入,只要用 PreparedStatement(从Statement扩展而来)取代Statement就可以了。
|
|
PreparedStatement
基本介绍

|
|
- PreparedStatement 执行的SQL语句中的参数用问号(?)来表示,调用 PreparedStatement对象的setXxx()方法来设置这些参数. setXxx()方法有两个参数,第一个参数是要设置的SQL语句中的参数的索引(从1开始),第二个是设置的SQL语句中的参数的值
- 调用executeQuery0),返回ResultSet 对象
- 调用executeUpdate():执行更新,包括增、删、修改
预处理好处
- 不再使用+拼接sql语句,减少语法错误
- 有效的解决了sql注入问题!
- 大大减少了编译次数,效率较高
应用案例
|
|
操作DML语句
|
|
JDBC 的相关 API 小结


封装JDBCUtils
说明
在jdbc操作中,获取连接和释放资源是经常使用到,可以将其封装DBC连接的工真类JDBCUtils。
代码实现
|
|
测试
|
|
事务
基本介绍
- JDBC程序中当一个Connection对象创建时,默认情况下是自动提交事务:每次执行一个SQL语句时,如果执行成功,就会向数据库自动提交,而不能回滚。
- JDBC程序中为了让多个SQL语句作为一个整体执行,需要使用事务
- 调用Connection的setAutoCommit(false)可以取消自动提交事务
- 在所有的SQL语句都成功执行后,调用Connection的commit();方法提交事务
- 在其中某个操作失败或出现异常时,调用Connection的rollback();方法回滚事务
应用实例
|
|
批处理
基本介绍
- 当需要成批插入或者更新记录时。可以采用Java的批量更新机制,这一机制允许多条语句一次性提交给数据库批量处理。通常情况下比单独提交处理更有效率。
- JDBC的批量处理语句包括下面方法:
addBatch():添加需要批量处理的SQL语句或参数executeBatch():执行批量处理语句;clearBatch():清空批处理包的语句
- JDBC连接MySQL时,如果要使用批处理功能,请在url中加参数
?rewriteBatchedStatements = true - 批处理往往和PreparedStatement一起搭配使用,可以既减少编译次数,又减小运行次数,效率大大提高。
|
|

数据库连接池
5k 次连接数据库问题
|
|
传统获取Connection 问题分析
- 传统的JDBC数据库连接使用 DriverManager 来获取,每次向数据库建立连接的时候都要将 Connection 加载到内存中,再验证IP地址,用户名和密码(0.05s~1s时间)。需要数据库连接的时候,就向数据库要求一个,频繁的进行数据库连接操作将占用很多的系统资源,容易造成服务器崩溃。
- 每一次数据库连接,使用完后都得断开,如果程序出现异常而未能关闭,将导致数据库内存泄漏,最终将导致重启数据库。
- 传统获取连接的方式,不能控制创建的连接数量,如连接过多,也可能导致内存泄漏,MySQL崩溃。
- 解决传统开发中的数据库连接问题,可以采用数据库连接池技术 (connection pool)。
数据库连接池种类
- JDBC 的数据库连接池使用javax.sqI.DataSource来表示,DataSource 只是一个接口,该接口通常由第三方提供实现[提供.jar]
- C3P0数据库连接池,速度相对较慢,稳定性不错(hibernate, spring)
- DBCP数据库连接池,速度相对c3p0较快,但不稳定
- Proxool数据库连接池,有监控连接池状态的功能,稳定性较c3p0差一点
- BoneCP数据库连接池,速度快
- **Druid(德鲁伊)**是阿里提供的数据库连接池,集DBCP、C3P0、Proxool优点于一身的数据库连接池

C3P0 应用实例

两种连接方式:
|
|
|
|
Druid(德鲁伊)应用实例
|
|
|
|
将JDBCUtils 工具类改成Druid(德鲁伊)实现
通过德鲁伊数据库连接池获取连接对象
|
|
|
|
Apache—DBUtils
先分析一个问题
- 关闭connection后,resultSet结果集无法使用
- resultSet不利于数据的管理
- 示意图
这种java类叫做JavaBean,PoJo或者Domain。

自定义方法解决
|
|
|
|
基本介绍
commons-dbutils是 Apache组织提供的一个开源JDBC工具类库,它是对JDBC的封装,使用dbutils能极大简化jdbc编码的工作量。
- DbUtils类:
- QueryRunner类:该类封装了SQL的执行,是线程安全的。可以实现增、删、改、查、批处理。
- 使用QueryRunner类实现查询。
- ResultSetHandler接口:该接口用于处理java.sql.ResultSet,将数据按要求转换为另一种形式。
- ArrayHandler:把结果集中的第一行数据转成对象数组。
- ArrayListHandler:把结果集中的每一行数据都转成一个数组,再存放到List中。
- BeanHandler:将结果集中的第一行数据封装到一个对应的JavaBean实例中。
- BeanListHandler: 将结果集中的每一行数据都封装到一个对应的JavaBean实例中,存放到List里。
- ColumnListHandler:将结果集中某一列的数据存放到List中。
- KeyedHandler(name):将结果集中的每行数据都封装到Map里,再把这些map再存到一个map里,其key为指定的key。
- MapHandler: 将结果集中的第一行数据封装到一个Map里,key是列名,value就是对应的值。
- MapListHandler:将结果集中的每一行数据都封装到一个Map里,然后再存放到List。
应用实例
使用DBUtils+数据连接池(德鲁伊)方式,完成对表actor的crud
|
|
表 和 JavaBean 的类型映射关系

DAO 和增删改查通用方法-BasicDao
先分析一个问题
apache-dbutils+ Druid简化了JDBC开发,但还有不足:
- SQL语句是固定,不能通过参数传入,通用性不好,需要进行改进,更方便执行增删改查
- 对于select 操作,如果有返回值,返回类型不能固定,需要使用泛型
- 将来的表很多,业务需求复杂,不可能只靠一个Java类完成
- 引出=》 BasicDAO画出示意图,看看在实际开发中,应该如何处理

基本说明
- DAO : data access object数据访问对象
- 这样的通用类,称为 BasicDao,是专门和数据库交互的,即完成对数据库(表)的crud操作。
- 在BaiscDao的基础上,实现一张表对应一个Dao,更好的完成功能,比如 Customer表-Customer.java类(javabean)-CustomerDao.java
BasicDAO 应用实例
完成一个简单设计com.hspedu.dao_
com.hspedu.dao _.utils//工具类com.hspedu.dao_.domain// javabeancom.hspedu.dao_.dao//存放XxxDAO和BasicDAO_com.hspedu.dao_.test//写测试类
com/hspedu/dao_/domain/Actor.java
|
|
com/hspedu/dao_/utils/JDBCUtilsByDruid.java
|
|
com/hspedu/dao_/dao/BasicDAO.java
|
|
com/hspedu/dao_/dao/ActorDAO.java
|
|
com/hspedu/dao_/test/TestDAO.java
|
|