JDBC标准与源码探究
JDBC概要描述
- 应用程序可以直接通过多种方式访问数据库,最普通的是通过socket访问数据库。以Mysql 为例:首先通过程序通过socket和数据库建立了TCP连接,把准备执行的SQL语句或命令封装成特定于Mysql 数据库的应用层数据包,发送给Mysql 数据库,Mysql数据库执行命令,将结果封装成数据包并返回给应用,应用程序进行解析,显示结果给客户端.
- 令人抓狂的是,Oracle, DB2,Postgresql等其他数据库都有一套属于自己的应用层访问协议。 他们的网络访问协议和Mysql 的完全不一样 ! 这就意味着之前写的针对Mysql 的程序无法针对其他数据库通用, 如果想切换数据库, 每个程序都得另起炉灶写一套代码!直接使用socket访问数据库耦合度太高了,必须得有一个抽象层屏蔽这些细节!
- 为此,JDK专门提供了一系列针对这个抽象层的统一接口—JDBC(Java Data Base Connectivity,java数据库连接),称为JDBC规范。数据库厂商需要实现JDBC规范中的某些接口(实现中应包含特定数据库的应用层协议的转换/解析等),这些接口统被称为 XX数据库驱动
jdbc的发展历程请参考这篇博客
- JDBC是一种Java web的规范,需要具体开发者(数据库厂商)来实现
- JDBC是Java访问关系型数据库的标准规范接口,真正怎么操作数据库还需要具体的实现类,也就是数据库驱动,数据库驱动由数据库厂商提供对应的jar包。每个数据库厂商根据自家数据库的通信格式编写好自己数据库的驱动。所以我们只需要使用多态方式调用 JDBC 接口中的方法即可。
所涉及到的包和主要接口
- 相关包
包 | 说明 |
---|---|
java.sql | 所有与JDBC访问数据库相关的接口和类 |
javax.sql | 数据库扩展包,提供数据库额外的功能。如:连接池 |
数据库的驱动 | 由各大数据库厂商提供,需要额外去下载,是对JDBC接口实现的类 |
- 相关接口与类
接口或类 | 作用 |
---|---|
DriverManager类 | 管理和注册数据库驱动;得到数据库连接对象Connection的实现类 |
Connection接口 | 一个连接对象,可用于创建Statement和PreparedStatement对象 |
Statement接口 | 一个SOL语句对象,用于将SQL语句发送给数据库服务器 |
PreparedStatement接口 | 一个SQL语句对象,是Statement的子接口 |
ResultSet接口 | 用于封装数据库查询的结果集,返回给客户端Java程序 |
JDBC常用四大API
- DriverManager
这是一个驱动管理类,一般情况下Driver要被注册进DriverManger中
作用:
1、注册驱动
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
// Class.forName("com.mysql.jdbc.Driver");// 推荐方式 这种方式会自己注册
2、获取连接
Connection conn = DriverManager.getConnection();
- Connection
作用:
1、创建执行SQL语句的对象(3种)
Statement createStatement() // 执行SQL语句
PreparedStatement prepareStatement() // 预编译SQL并执行
CallableStatement prepareCall() // 执行SQL存储过程
2、进行事务管理
setAutoCommit(boolean b)
commit()
rollback()
- Statement
statement包含的方法,都是与数据库操作相关的方法
作用:
1、执行SQL语句
boolean execute(String sql) // 执行SQL语句,执行select就返回true,否则返回false
ResultSet executeQuery(String sql) // 执行SQL中的select语句
int executeUpdate(String sql) // 执行SQL中的insert/update/delete语句
2、执行批量SQL语句
addBatch(String sql) // 添加到批量处理
executeBatch() // 执行批量处理
clearBatch() // 清空批量处理
- ResultSet
(select语句)查询结果的集合
作用:获取到查询的结果
next() //判断是否有下一条数据
getXXX() //根据数据类型获取查询记录的数据
getObject() //通用获取数据方法
JDBC资源释放
释放原则:晚创建,早释放;资源稀有,不释放很快会阻塞
Connection conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb","root","root");
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("select * from user");
rs.close();
stmt.close();
conn.close();
JDBC CURD操作
下图大致可以展示连接、查询、数据返回之间的关系
- 增加
Connection conn = null;
Statement stmt = null;
try{
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获得连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 获取执行SQL语句对象
stmt = conn.createStatement();
// 编写SQL
String sql = "insert into user values ("xiaomin","女人",12)";
// 执行SQL语句
int i = stmt.executeUpdate(sql);
if(i > 0){
System.out.println("插入成功!");
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
- 删除
代码与增加类似
- 修改
代码与增加类似
- 查询
代码与增加类似
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
try{
// 注册驱动
Class.forName("com.mysql.jdbc.Driver");
// 获得连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/myDB","root","root");
// 获取执行SQL语句对象
stmt = conn.createStatement();
// 编写SQL
String sql = "select * from user";
// 执行SQL语句
rs = stmt.executeQuery(sql);
if(rs.next()){
System.out.print(rs.getString("name"));
}
}catch(Exception e){
e.printStackTrace();
}finally{
if(rs != null){
try{
rs .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
rs = null;
}
}
if(stmt != null){
try{
stmt .close();
}catch(SQLException e){
e.printStackTrace();
}finally{
stmt = null;
}
}
if(conn != null){
try{
conn.close();
}catch(SQLException e){
e.printStackTrace();
}finally{
conn = null;
}
}
}
连接池(数据源)
持续更新中.....(正在试图写一个数据连接池和数据库驱动)
数据库连接频繁创建与消耗,在资源使用上是一种浪费
- 常用连接池
C3P0、HikariCP、Druid、Tomcat、Dbcp- 用法(以C3P0为例)
ComboPooledDataSource dataSource = new ComboPooledDataSource(); // 只需一个对象 // 获取连接 Connection conn = dataSource.getConnection();
java.sql简介
这段内容的主要参考文档是JDK源码
及其API文档
以及官方发布的JDBC4.2标准
-----------------未完 待续----------------------
SQL 类型 | Jdbc 对应方法 | 返回类型 |
---|---|---|
BIT(1) bit(n) | getBoolean() | boolean |
TINYINT | getByte() | byte |
SMALLINT | getShort() | short |
INT | getInt() | int |
BIGINT | getLong() | long |
CHAR,VARCHAR | getString() | String |
Text(Clob) Blob | getClob getBlob() | Clob Blob |
DATE | getDate() | java.sql.Date 只代表日期 |
TIME | getTime() | java.sql.Time 只表示时间 |
TIMESTAMP | getTimestamp() | java.sql.Timestamp 同时有日期和时间 |
所使用到的设计模式
jdbc使用的设计模式:
桥梁设计模式:
DriverManager有一个集合存放DriverInfo(该类关联一个Driver)
DriverManager调用getConnection方法时,找到相应的DriverInfo创建Connection
Driver是面向数据库,具体的Driver由数据库提供
jdbc的spi框架正式通过桥梁设计模式来实现的:
- 服务管理者:DriverManage
- 服务提供者接口:Driver
- 服务接口:Connection
工厂方法设计模式:
具体数据库的Driver生成具体的Connection
参考:
- JDBC规范与实现 详细解读
- 数据库连接池技术详解
- https://segmentfault.com/a/1190000007989074
- mysql jdbc 驱动解析