JDBC驱动加载全过程(转)

第一次看到JDBC这个东西的时候,就猜到JDBC应该是Java DataBase Connection的缩写,作用应该就是让java和数据库取得连接,真正开始学的时候,发现正如我猜想的那样,JDBC就是Java应用程序和数据库之间的一道桥梁,唯一猜的不对的就是它是Java DataBase Connectivity的缩写,不过无伤大雅。好了,废话不多说,下面我们直接进入正题。

话说林子大了,什么数据库都有,比如Oracle、MySQL、SQL server等等,每种数据库都有其各自的连接方法,但此时Java就不开心了,它就想:这么多方法我都要干,岂不是要累死,我坚决不能按照你们的规定做,我要做制定标准的那一方,你们这些杂七杂八的数据库必须按照我的规矩来,于是Java就制定了一套连接数据库的标准接口,也就是我们所说的JDBC。各个数据库厂商实现这些接口,这样Java和数据库的连接就不用那么麻烦了。

说了这么多,相信现在大家也应该知道了,一个Java应用程序要想和数据库进行连接,那么就不得不调用JDBC接口,那么第一步要做的就是把数据库厂商的驱动程序加载进系统内存,供系统使用,结构如下图

1.png

上面我们所说的驱动不过也只是实现了java.sql.driver接口的一个类,如Oracle的驱动类是oracle.jdbc.driver.OracleDriver.class(此类可以在oracle提供的JDBCjar包中找到),此类实现了java.sql.Driver接口。由于驱动的本质是一个类,所以加载驱动的过程其实就是加载类的过程,下面是常用的加载数据库驱动的具体代码:

1

加载Oracle数据库驱动

Class.forName("oracle.jdbc.driver.OracleDriver");

2

加载SQL Server数据库驱动

Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");

3

加载MySQL 数据库驱动

Class.forName("com.mysql.jdbc.Driver");

上面我们可以看到,加载驱动使用的是Class这个类的forName方法(关于Class类,后续有机会再写一篇文章单独介绍),下面是这张图就是Class的forName方法的API

2.png

当我们在使用Class.forName() 加载oracle的驱动oracle.jdbc.driver.OracleDriver时,会执行OracleDriver中的静态代码段,创建一个OracleDriver实例,然后调用DriverManager.registerDriver()注册,之后就可以利用DriverManager获取连接,从而进行java和数据库之间的对话。下面是我在网上找到的OracleDriver中的静态代码块

7.png

从图中我们可以发现,当我们创建一个新的OracleDriver实例时,紧接着就会把该实例向DriverManager进行注册。下面是我通过手动创建OracleDriver实例,验证一下其是否真的会自动向DriverManager进行注册。

3.png

运行结果(看来真的是这么回事):

4.png

关于Driver接口,JDK1.6API这么介绍该接口:每个驱动程序类必须实现的接口。Java SQL 框架允许多个数据库驱动程序。每个驱动程序都应该提供一个实现 Driver 接口的类。DriverManager 会试着加载尽可能多的它可以找到的驱动程序,然后,对于任何给定连接请求,它会让每个驱动程序依次试着连接到目标 URL。强烈建议每个 Driver 类应该是小型的并且是单独的,这样就可以在不必引入大量支持代码的情况下加载和查询 Driver 类。在加载某一 Driver 类时,它应该创建自己的实例并向 DriverManager 注册该实例。这意味着用户可以通过调用以下程序加载和注册一个驱动程序Class.forName("foo.bah.Driver")。下面是Driver接口定义的方法:

5.png

其中比较重要的两个方法时boolean acceptsURL(String url)和Connection connect(String url,Properties info)。

 boolean acceptsURL(String url)方法:用来测试对指定的url,该驱动能否打开这个url连接。driver对自己能够连接的url会制定自己的协议,只有符合自己的协议形式的url才认为自己能够打开这个url,如果能够打开,返回true,反之,返回false;

connect(String url,Properties info)方法:创建Connection对象,用来和数据库的数据操作和交互,而Connection则是真正数据库操作的开始(在此方法中,没有规定是否要进行acceptsURL()进行校验),方法中的参数url是要连接到的数据库的URL,info作为连接参数的任意字符串标记/值对的列表。通常至少应该包括user和password属性。

下面是我仅仅利用这两个方法,跳过DriverManager驱动管理,创建和数据库的连接,结果自然也是成功的。

6.png

那么问题来了,既然我们直接可以通过Driver的实现建立和数据库的连接,为什么还要使用DriverManager驱动管理呢?原因在于上述的连接过程稍显麻烦,而且如果现在我们加载进来了多个驱动Driver,那么手动创建Driver实例,并根据URL进行创建连接就会显得代码杂乱无章,并且还容易出错,并且不方便管理。于是乎JDBC中为我们提供了一个DriverManager角色,用来管理这些驱动Driver。

关于DriverManager接口:JDK1.6API中说它管理一组 JDBC 驱动程序的基本服务。下面是它的主要API:

8.png

仔细查看它的API,我们会发现它的所有方法都为静态方法,也就意味着我们不用实例化,可以直接进行调用。

DriverManager 内部持有这些注册进来的驱动 Driver,由于这些驱动都是 java.sql.Driver 类型,那么怎样才能获得指定厂商的驱动Driver呢?答案就在于: java.sql.Driver接口规定了厂商实现该接口,并且定义自己的URL协议。厂商们实现的Driver接口通过acceptsURL(String url)来判断此url是否符合自己的协议,如果符合自己的协议,则可以使用本驱动进行数据库连接操作,查询驱动程序是否认为它可以打开到给定 URL 的连接。下面详细讲一下它最重要的三个作用:

1、使用DriverManager获取指定的Driver

对于驱动加载后,如何获取指定的驱动程序呢?这里,DriverManager的静态方法getDriver(String url)可以通过传递给的URL,返回可以打开此URL连接的Driver。比如我想获得Oracle的数据库驱动,只需要将Oracle规定的url参数形式传递进去就可以Oracle的数据库驱动

9.png

输出结果:

10.png

实际上,DriverManager.getDriver(String url)方法是根据传递过来的URL,遍历它维护的驱动Driver,依次调用驱动的Driver的acceptsURL(url),如果返回acceptsURL(url)返回true,则返回对应的Driver

2、注册和删除驱动程序

在本文的第一个实例中,我们验证了驱动的自动注册,现在我们来验证驱动注册是否为必须要做的事情。首先我利用上述的方法,获取已加载驱动,然后利用DriverManage的static void deregisterDriver(Driver driver)方法删除已加载驱动,然后执行程序,程序会报无法找到指定url的驱动程序

11.png

12.png

上述实验证明了注册驱动为必须的事情,现在我再手动添加创建一个OracleDriver实例并进行注册,然后运行程序。

13.png

14.png

到这里,我们已经能确定的说,向DriverManager注册驱动是一件必须的事情,但此时我发现了一个问题,开头不是说创建一个OracleDriver实例就会自动向DriverManager注册驱动吗?怎么这里还必须要手动注册驱动呢?经过我的反复试验得出的结论就是:在一个程序中,只有第一次创建OracleDriver实例时,才会自动进行驱动的注册,也就是说static静态块只会执行一次,所以当我们将驱动列表的Oracle数据驱动删除之后,列表中将不会再含有Oracle数据驱动,此时如果再创建OracleDriver实例,将不会自动向DriverManager注册驱动,只能通过手动进行驱动注册。

3、使用DriverManager获取连接

通过DriverManager的getConnection(String url,String user, String password)获取与指定数据库的连接,上面的一些事例代码中已经使用的此种方法,所以不再赘述。

猜你喜欢

转载自blog.csdn.net/BinGuoLA/article/details/81432255