日期:2014-05-16  浏览次数:20606 次

Inside JDBC(一)

?

???? 现在的Java应用开发,涉及到数据库操作的时候,大家往往首先想到的是Hibernate之类的ORM框架。越来越少的Java开发人员愿意去使用或者深入学习JDBC,实际上ORM框架最终还是要使用JDBC的。在这篇文章中,我将比较全面的介绍JDBC的基础知识。本文说到的数据库主要是以主流的关系数据库为主。
?? ? 数据库产品之多,例如波音级别的Oracle,宝马级别的MySQL各个数据库产品,无论是商业数据库还是开源数据库都有一套自己的API用于外部程序与自身交互。如果开发人员面对每一款数据库产品都需要去学习一个新的API,那将是很不情愿的一件事情,因为学习成本往往是比较高的。大家学习Java的时候要时常记住一句话“混乱之时标准将出现”。Sun Microsystems为了解决这个问题,受微软ODBC标准的启发,定义了JDBC规范,到现在为止,JDBC已发展到了4.0版本。JDBC(Java DataBase Connectivity)定义了Java访问数据库的标准,主要以一套接口的形式体现,定义在java.sql和javax.sql包之中。所谓JDBC驱动,既是数据库厂商对JDBC规范的Java实现,打包成jar归档文件,在数据库厂商的官网多有下载。JDBC驱动有四种类型,本文已用的最多的Type 4为例。JDK的发布中包含了JDBC-ODBC桥驱动,这种类型多数用于访问MS Access以及Excel,本文不予以介绍。
???? 有了JDBC后,Java开发人员只需要学习JDBC API既可,不需要考虑底层数据库产品的差异。比如发生了更换数据库产品的情况,从SQL Server变更到Oracle,我们只需要更换JDBC驱动既可。假设没有使用数据库产品特有SQL的话,如SQL Server 的top关键字,JDBC代码几乎无需改动,达到了跨数据库平台的效果。
???? 更复杂的情况就是,一个Java应用需要访问多个数据库产品,比如需要同时访问MySQL和Oracle。也就是说需要两个数据库驱动,这些驱动谁来管理呢?答案是驱动管理器,即类java.sql.DriverManager。DriverManager有一静态方法 static void registerDriver(java.sql.Driver driver),此方法用于注册需要被管理的驱动(Driver)。java.sql.Driver
是一接口,定义了一个非常重要的方法:java.sql.Connection connect(String url, java.util.Properties info)此方法返回Java应用操作数据库所需的数据库连接。参数url指定了“连接字符串”,格式为:jdbc:subprotocol:subname。例如"jdbc:mysql://localhost:3306/mydb",info参数用于传递额外信息,比如用户名,密码等。作为数据库驱动的实现者,如MySQL的Connector/J,提供的驱动实现类必须实现Driver接口,如com.mysql.jdbc.Driver类就实现了java.sql.Driver接口,我们来看其中一段非常有趣的代码(来自MySQL驱动源码):

?

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
   //静态初始化块
   static {
        try {
             java.sql.DriverManager.registerDriver(new Driver());
        } catch (SQLException E) {
             throw new RuntimeException("Can't register driver!");
        }
  }
   //...
}


?

大家知道,静态初始化块是在Java虚拟机类加载器(JVM ClassLoader)加载相应类的时候执行初始化的。也就是说在执行 Class.forName("com.mysql.jdbc.Driver")时执行了com.mysql.jdbc.Driver内部的静态初始化块。此静态初始化块只做了一件事,把自己(new Driver())注册给了DriverManager。在DriverManager内部用java.util.Vector存放注册了的驱动。如果大家有兴趣,可以反编译一下微软实现的SQL Server的驱动程序(不开源,所以要反编译)也有一个静态初始化块用于注册。现在我们来看一个完整点的程序:

?

//使用的MySQL驱动版本为Connector/J-5.1.7
package com.wwei.jdbc;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
public class DirverInfo {
     public static void main(String[] args)throws Exception {
         Class.forName("com.mysql.jdbc.Driver");//加载驱动并注册驱动
         Driver driver = DriverManager.getDriver("jdbc:mysql://");//通过url获得驱动
         System.out.println(driver.getMajorVersion());//驱动主版本 5
         System.out.println(driver.getMinorVersion());//驱动次版本 1
         //获得驱动支持的特性,输出的名值对大家可以对照Connector/J文档查阅其含义。
         DriverPropertyInfo [] dpis = driver.getPropertyInfo("jdbc:mysql://localhost/test", null);
         for(DriverPropertyInfo info : dpis){
             System.out.println(info.name + " = " + info.value);
         }
}



}

?

接下来我们来看一下DriverManager的另外一个重要方法:
public static Connection getConnection(String url,String user,String password)
此方法的内部实现有以下几句代码(来自JDK src.zip):


Connection result = di.driver.connect(url, info);
if (result != null) {
    // Success!
    println("getConnection returning " + di);
    return (result);
}


?

di.driver.connect(url,info)既是上述java.sql.Driver接口的connect方法,具体的实现在com.mysql.jdbc.Driver类中。

关于DriverManager的更多方法,大家可以查阅Java文档,下一篇将介绍JDBC的具体用法。



???