前言:自己的小理解和大部分javasec内容
JDBC
什么是JDBC?
JDBC本质:官方定义的一套操作所有关系型数据库的规则,即接口。 各个数据库厂商去实现了这个JDBC的接口,提供数据库驱动jar包,我们可以使用这套接口JDBC编程,真正执行代码的是驱动jar包中的实现类
什么是"真正执行代码的是驱动jar包中的实现类",其实就是一个类去实现官方写的接口中的方法,这样就是一个实现类!
那么厂商们要实现哪个哪个接口呢? java.sql.Driver
跟进去看下,如下的方法都是厂商们一定需要实现的方法!!!
public interface Driver //这是一个接口,不用说,要不然其他厂商如何实现呢!
Connection connect(String url, java.util.Properties info)
boolean acceptsURL(String url) //还能判断是否是正规的数据库协议
DriverPropertyInfo[] getPropertyInfo // 该方法可以获得一些驱动的相关信息放到DriverPropertyInfo数组中
int getMajorVersion(); //获取主版本信息
int getMinorVersion(); //获取副版本信息
boolean jdbcCompliant(); //判断驱动程序是否为正版JDBC
public Logger getParentLogger() //返回此驱动程序使用的所有记录器的父记录器
可以看下Mysql中的驱动包是如何写的,如下显示,这里它通过继承NonRegisteringDriver类来实现了java.sql.Driver的接口
java.sql.DriverManager
Java通过java.sql.DriverManager来管理所有数据库的驱动注册,所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册registerDriver对应的驱动类,然后调用getConnection方法才能连接上数据库。
跟进去简单的了解下DriverManager这个类的属性和方法
这是一个公有类public class DriverManager
如下属性:注册的JDBC驱动程序列表
// List of registered JDBC drivers
private final static CopyOnWriteArrayList<DriverInfo> registeredDrivers = new CopyOnWriteArrayList<>(); //这个是用来保存已经注册过的驱动
private static volatile int loginTimeout = 0;
private static volatile java.io.PrintWriter logWriter = null;
private static volatile java.io.PrintStream logStream = null;
一个静态代码块:
static {
loadInitialDrivers();
println("JDBC DriverManager initialized");
}
还有一些关于日志的操作:
public static java.io.PrintWriter getLogWriter()
public static void setLogWriter(java.io.PrintWriter out)
....
....
获取数据库的连接:
public static Connection getConnection(String url, java.util.Properties info)
public static Connection getConnection(String url, String user, String password)
public static Connection getConnection(String url)
private static Connection getConnection(String url, java.util.Properties info, Class<?> caller)
驱动的相关操作:
public static Driver getDriver(String url) //获取驱动
public static synchronized void registerDriver(java.sql.Driver driver) //注册驱动1
public static synchronized void registerDriver(java.sql.Driver driver, DriverAction da) //注册驱动2
public static synchronized void deregisterDriver(Driver driver) //取消驱动
一个概念:Java通过java.sql.DriverManager来管理所有数据库的驱动注册,所以如果想要建立数据库连接需要先在java.sql.DriverManager中注册对应的驱动类,然后调用getConnection方法才能连接上数据库。
java.sql.DriverManager.getConnection(xx)其实就是间接的调用了java.sql.Driver类的connect方法实现数据库连接的。数据库连接成功后会返回一个叫做java.sql.Connection的数据库连接对象,一切对数据库的查询操作都将依赖于这个Connection对象。
JDBC连接数据库的一般步骤:
1、注册驱动,Class.forName("数据库驱动的类名")
2、获取连接,DriverManager.getConnection(xxx)
正常实现的代码如下
Class.forName("com.mysql.jdbc.Driver");
String URL = "jdbc:mysql://localhost:3306/mysql";
String USERNAME = "root";
String PASSWORD = "123456";
Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
我自己学的时候反正是有疑问的,为什么注册用Class.forName("com.mysql.jdbc.Driver");
来实现,然后就是DriverManager.getConnection
为什么能够获得Mysql驱动包中的connection对象
这两个问题得解决!
为什么Class.forName能够实现注册驱动
那么直接跟进com.mysql.jdbc.Driver的Driver类中去观察
看下如下的内容,这是一个静态代码块,并且Class.forName("com.mysql.jdbc.Driver")
使用的时候会触发类加载,从而执行该静态代码块,那么也就可以说明了,为什么能够Class.forName("com.mysql.jdbc.Driver")
能够注册驱动!
提醒,如果想拿到对应类型的Class实例,但是又不想触发类加载执行静态代码块的话,下面两种方法可以解决:
1、使用Class.forName("xxxx", false, loader)
方法,将第二个参数传入false。
2、ClassLoader.load("xxxx");
DriverManager.getConnection为什么能够获得Mysql
那么也从源码中观察,老样子跟进DriverManager中,静态代码块执行的是DriverManager.registerDriver(new Driver());
继续跟registerDriver方法,如下图所示,它会将Mysql自身Driver实例化然后放到registerDriver中
最后还会添加到registeredDrivers属性中
然后现在就是Connection connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
我们可以看下DriverManager.getConnection的方法是怎么样的,如下图所示,它会将账号密码这些都存储起来然后放到一个info对象中,再将info作为参数传入getConnection中
跟进去看,重点是如下的红框处,它的for循环会遍历registeredDrivers数组,取出DriverInfo类型的aDriver变量,DriverInfo这个就是之前存储到registeredDrivers数组中的内容,此时的aDriver.driver就是已经实例化的Driver对象(Mysql,Mssql等等),最后调用它们实现Driver接口之后的connect方法,返回一个connection的对象!!!