之前在面试的时候被问到在使用jdbc的时候为什么需要注册驱动的步骤,在注册驱动之后驱动代码是怎么被执行到的,之前只知道简单的使用,被问到具体原理的时候就懵逼了。现在有空来深入总结一下jdbc的使用原理。
一.jdbc的使用
主要分为5个步骤:
- 注册驱动
- 获取数据库连接Connection
- 获取数据库操作对象Statement
- 执行SQL语句
- 处理查询结果集ResultSet
- 关闭资源 倒序依次关闭
源码地址:https://github.com/shelimingming/jdbc-demo
package com.sheliming.jdbc.demo;
import java.sql.*;
/**
* jdbc使用demo
*/
public class JDBCDemo {
public static void main(String[] args) {
Connection conn = null;// 数据库连接对象
Statement stmt = null;// 数据库操作对象
ResultSet rs = null;// 查询结果集对象
try {
//1.注册驱动
Class.forName("com.mysql.jdbc.Driver");
//手动注册
//Driver driver = new com.mysql.jdbc.Driver();
//DriverManager.registerDriver(driver);
//2.获取数据库连接
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
String user = "root";
String password = "123456";
conn = DriverManager.getConnection(url, user, password);
System.out.println(conn);
//3.获取数据库操作对象
stmt = conn.createStatement();
System.out.println(stmt);
//4.执行SQL语句之DML语句
String sql = "select * from user";
rs = stmt.executeQuery(sql);
System.out.println(rs);
/*
+----+--------+------+------------------+
| id | name | sex | email |
+----+--------+------+------------------+
*/
//5、处理查询结果集
while (rs.next()) {
int id = rs.getInt("id");
String name = rs.getString("name");
String sex = rs.getString("sex");
String email = rs.getString("email");
System.out.println("编号" + id + "\t" + "姓名" + name + "\t" + "性别" + sex + "\t" + "邮箱" + email);
}
} catch (SQLException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
} finally {
// 6、关闭资源 倒序依次关闭
//6.1 当查询结果集不为空时,先关闭结果集对象
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//6.2 当数据库操作对象不为空时,再关闭数据库操作对象
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//6.3 当数据库连接对象不为空时,最后关闭数据库连接对象
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
建表语句:
/*
Navicat MySQL Data Transfer
Source Server : local
Source Server Version : 80013
Source Host : localhost:3306
Source Database : test
Target Server Type : MYSQL
Target Server Version : 80013
File Encoding : 65001
Date: 2019-01-30 23:06:00
*/
SET FOREIGN_KEY_CHECKS=0;
-- ----------------------------
-- Table structure for user
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) DEFAULT NULL,
`sex` varchar(2) DEFAULT NULL,
`email` varchar(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'aaa', 'a', 'a');
INSERT INTO `user` VALUES ('2', 'bbb', 'b', 'b');
INSERT INTO `user` VALUES ('3', 'ccc', 'c', 'c');
二.驱动加载过程
这里所谓的驱动,其实就是实现了java.sql.Driver接口的类。如oracle的驱动类是 oracle.jdbc.driver.OracleDriver,mysql就是com.mysql.jdbc.Driver。
//加载Oracle数据库驱动
Class.forName("oracle.jdbc.driver.OracleDriver");
//加载SQL Server数据库驱动
Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
//加载MySQL 数据库驱动
Class.forName("com.mysql.jdbc.Driver");
Class.forName()将对应的驱动类加载到内存中,然后执行内存中的static静态代码段,代码段中,会创建一个驱动Driver的实例,放入DriverManager中,供DriverManager使用。
首先我们看下com.mysql.jdbc.Driver这个类,在新版本的mysql连接包中使用com.mysql.cj.jdbc.Driver.
如下:
其中最要的就是这个静态代码块,在反射出这个对象之后就会执行这块静态代码块,将Driver对象放到DriverManager中,这就回答了一开始的那个问题。
主要实现了java.sql.Driver这个接口
三.手动加载驱动 Driver 并实例化进行数据库操作的例子
package com.sheliming.jdbc.my;
import java.sql.Connection;
import java.sql.Driver;
import java.util.Properties;
public class MyJdbc {
public static void driverTest() {
try {
//1.加载mysql驱动类,并实例化
Driver driver = (Driver) Class.forName("com.mysql.jdbc.Driver").newInstance();
//甚至可以直接这样写
//Driver driver = new com.mysql.jdbc.Driver();
//2.判定指定的URL mysql驱动能否接受
boolean flag = driver.acceptsURL("jdbc:mysql://localhost:3306/test?serverTimezone=UTC");
System.out.println("协议测试:" + flag);
//3.创建真实的数据库连接:
String url = "jdbc:mysql://localhost:3306/test?serverTimezone=UTC";
Properties props = new Properties();
props.put("user", "root");
props.put("password", "123456");
Connection connection = driver.connect(url, props);
System.out.println(connection);
} catch (Exception e) {
System.out.println("加载mysql类失败!");
e.printStackTrace();
} finally {
}
}
public static void main(String[] args) {
driverTest();
}
}
可见自己注册Driver是一种非常麻烦的事情,所以jdbc提供了DriverManage的东西,我们就可以像第一个demo一样使用DriverManage去获取Connection。这样可以同时管理多个驱动程序,根据传入的参数不同,返回不同的数据连接。