JAVA JDBC connection

前言:自己的小理解和大部分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的对象!!!

原文地址:https://www.cnblogs.com/zpchcbd/p/13492177.html