JDBC简介(1)

1、JDBC工作的基本流程

一个基本的JDBC工作流程,分为以下几步:

1.加载特定数据库驱动器实现类,并注册驱动器(Driver会注册到DriverManager中);

2.根据特定的URL,返回可以接受此URL的数据库驱动对象Driver;

3.使用数据库驱动Driver创建数据库连接Connection会话;

4.使用 Connection对象创建用于操作sql的Statement对象;

5.statement对象 .执行sql语句,返回结果ResultSet 对象;

6.处理ResultSet中的结果;

7.关闭连接,释放资源。


以下是一个简单的案例:

public class DBConnection {  
  
    static final String  URL = "jdbc:oracle:thin:@127.0.0.1:1521:xe";  
    static final String USER_NAME ="louluan";  
    static final String PASSWORD = "123456";  
      
    public static void main(String[] args) {  
        connectionTest();  
    }  
      
    public static void connectionTest(){  
          
        Connection connection = null;  
        Statement statement = null;  
        ResultSet resultSet = null;  
          
        try {  
            //1.加载类,并注册驱动器(Driver会注册到DriverManager中)  
              
            //加载Oracle数据库驱动  
            Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();  
              
            //2.根据特定的URL,返回可以接受此URL的数据库驱动对象  
            Driver driver = DriverManager.getDriver(URL);  
            Properties props = new Properties();  
            props.put("user", USER_NAME);  
            props.put("password", PASSWORD);  
              
            //3.使用数据库驱动创建数据库连接Connection会话  
            connection = driver.connect(URL, props);  
              
            //4.获得Statement对象  
            statement = connection.createStatement();  
            //5.执行 sql语句,返回结果  
            resultSet = statement.executeQuery("select * from hr.employees");  
            //6.处理结果,取出数据  
            while(resultSet.next())  
            {  
                System.out.println(resultSet.getString(2));  
            }  
              
            //7.关闭链接,释放资源  
        } catch (ClassNotFoundException e) {  
            System.out.println("加载Oracle类失败!");  
            e.printStackTrace();  
        } catch (SQLException e) {  
            e.printStackTrace();  
        } catch (InstantiationException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            // TODO Auto-generated catch block  
            e.printStackTrace();  
        }finally{  
                //使用完成后管理链接,释放资源,释放顺序应该是: ResultSet ->Statement ->Connection  
                try {  
                    resultSet.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
                  
                try {  
                    statement.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
                  
                try {  
                    connection.close();  
                } catch (SQLException e) {  
                    e.printStackTrace();  
                }  
        }  
    }  
} 

JDBC工作时序图:

     上述几个对象之间:DriverManager或者Driver创建Connection、Connection创建Statement、Statement又获得ResultSet,它们之间的交互序列图如下所示: 


2、 JDBC的层次结构

总体而言,JDBC包含以下几大角色 : Driver、DriverManager、Connection、Statement、ResultSet。这几大角色之间的层次关系如下图所示:


2.1 Driver

一般情况下,在应用程序中进行数据库连接,调用JDBC接口,首先要将特定厂商的JDBC驱动实现加载到系统内存中,然后供系统使用。基本结构图如下:


驱动加载入内存的过程
    这里所谓的驱动,其实就是实现了java.sql.Driver接口的类。如oracle的驱动类是 oracle.jdbc.driver.OracleDriver.class(此类可以在oracle提供的JDBC jar包中找到),此类实现了java.sql.Driver接口。由于驱动本质上还是一个class,将驱动加载到内存和加载普通的class原理是一样的:使用Class.forName("driverName")。以下是将常用的数据库驱动加载到内存中的代码:

//加载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使用。
例如,在使用Class.forName() 加载oracle的驱动oracle.jdbc.driver.OracleDriver时,会执行OracleDriver中的静态代码段,创建一个OracleDriver实例,然后调用DriverManager.registerDriver()注册:

static {  
    Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0");  
    try {  
        if (defaultDriver == null) {  
            //创建一个OracleDriver实例,然后注册到DriverManager中  
                               defaultDriver = new OracleDriver();  
            DriverManager.registerDriver(defaultDriver);  
        }  
  
    } catch (RuntimeException localRuntimeException) {  
    } catch (SQLException localSQLException) {  
    } 
Driver的功能:
java.sql.Driver接口规定了Driver应该具有以下功能:


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


例如:oracle定义的自己的url协议如下:
jdbc:oracle:thin:@//<host>:<port>/ServiceName
jdbc:oracle:thin:@<host>:<port>:<SID>


2.2 DriverManager角色

事实上,一般我们操作Driver,获取Connection对象都是交给DriverManager统一管理的。DriverManger可以注册和删除加载的驱动程序,可以根据给定的url获取符合url协议的驱动Driver或者是建立Conenction连接,进行数据库交互。


以下是DriverManager的关键方法摘要:


DriverManager内部持有这些注册进来的驱动 Driver,由于这些驱动都是 java.sql.Driver 类型,那么怎样才能获得指定厂商的驱动Driver呢

答案就在于:java.sql.Driver接口规定了厂商实现该接口,并且定义自己的URL协议。厂商们实现的Driver接口通过acceptsURL(String url)来判断此url是否符合自己的协议,如果符合自己的协议,则可以使用本驱动进行数据库连接操作,查询驱动程序是否认为它可以打开到给定 URL 的连接。


使用DriverManager获取指定Driver

     对于驱动加载后,如何获取指定的驱动程序呢?这里,DriverManager的静态方法getDriver(String url)可以通过传递给的URL,返回可以打开此URL连接的Driver。比如,我想获取oracle的数据库驱动,只需要传递形如jdbc:oracle:thin:@<host>:<port>:<SID>或者jdbc:oracle:thin:@//<host>:<port>/ServiceName的参数给DriverManager.getDriver(String url)即可:

Driver oracleDriver =DriverManager.getDriver("jdbc:oracle:thin:@<host>:<port>:<SID>");
实际上,DriverManager.getDriver(String url)方法是根据传递过来的URL,遍历它维护的驱动Driver,依次调用驱动的Driver的acceptsURL(url),如果返回acceptsURL(url)返回true,则返回对应的Driver: 

public static Driver getDriver(String paramString) throws SQLException {  
  
    //省略部分代码。。。。  
    Iterator localIterator = registeredDrivers.iterator();  
    //遍历注册的驱动  
    while (localIterator.hasNext()) {  
        DriverInfo localDriverInfo = (DriverInfo) localIterator.next();  
        if (isDriverAllowed(localDriverInfo.driver, localClass))  
            try {  
                //如果accepsURL() 为true,返回对应的driver  
                if (localDriverInfo.driver.acceptsURL(paramString)) {  
                    //返回对应的driver  
                    return localDriverInfo.driver;  
                }  
            } catch (SQLException localSQLException) {  
            }  
        else  
            println("    skipping: "+ localDriverInfo.driver.getClass().getName());  
    }  
    throw new SQLException("No suitable driver", "08001");  
    //-----省略部分代码  
} 

使用DriverManager创建Connection连接对象

创建 Connection 连接对象,可以使用驱动Driver的 connect(url,props),也可以使用 DriverManager 提供的getConnection()方法,此方法通过url自动匹配对应的驱动Driver实例,然后调用对应的connect方法返回Connection对象实例。

Driver driver  = DriverManager.getDriver(url);  
Connection connection = driver.connect(url, props);

  
上述代码等价于:
Class.forName("oracle.jdbc.driver.OracleDriver");  
Connection connection = DriverManager.getConnection(url, props);  

jdbc.drivers:

      DriverManager 作为 Driver 的管理器,它在第一次被使用的过程中(即在代码中第一次用到的时候),它会被加载到内存中,然后执行其定义的static静态代码段,在静态代码段中,有一个  loadInitialDrivers()  静态方法,用于加载配置在jdbc.drivers 系统属性内的驱动Driver,配置在jdbc.drivers 中的驱动driver将会首先被加载:

static {  
    loadInitialDrivers();//加载配置在jdbc.drivers系统变量中的驱动driver  
    println("JDBC DriverManager initialized");  
    SET_LOG_PERMISSION = new SQLPermission("setLog");  
}  


private static void loadInitialDrivers() {  
    String str1;  
    try {  
        str1 = (String) AccessController  
                .doPrivileged(new PrivilegedAction() {  
                    public String run() {  
                        return System.getProperty("jdbc.drivers");//返回jdbc.drivers值  
                    }  
                });  
    } catch (Exception localException1) {  
        str1 = null;  
    }  
  
               //省略部分代码......  
    if ((str1 == null) || (str1.equals("")))  
        return;  
    String[] arrayOfString1 = str1.split(":");  
    println("number of Drivers:" + arrayOfString1.length);  
    for (String str2 : arrayOfString1)  
        try {  
            //Class.forName加载对应的driver  
            Class.forName(str2, true, ClassLoader.getSystemClassLoader());  
        } catch (Exception localException2) {  
            println("DriverManager.Initialize: load failed: "  
                    + localException2);  
        }  
} 


以下是通过jdbc.drivers加载驱动driver的方式:

String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";  
//设置值系统变量jdbc.drivers  
System.setProperty("jdbc.drivers", "oracle.jdbc.driver.OracleDriver");  
//2.通过特定的url获取driver  
Driver driver = DriverManager.getDriver(url);  
//打印是否存在  
System.out.println(driver); 

请记住:一定要在第一次使用DriverManager之前设置jdbc.drivers,因为DriverManager中的static静态代码段只会被执行一次!


后续:JDBC简介(2)



参考来源:

老调重弹:JDBC系列 之 <驱动加载原理全面解析> 




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值