JDBC模型—深入理解JDBC设计思想(探究Class.forName("DBDriver"))

来源:互联网 发布:第五代网络播放机骗局 编辑:程序博客网 时间:2024/06/06 04:26

写在前面:笔者上篇文章《JDBC要点总结、SQL注入示例(Statement和PreparedStatement)》中提到过,JDBC是sun公司制定的一系列接口标准,由不同厂商(Oracle、MySQL等)实现接口方法并封装成驱动文件,供开发人员操作数据库。开发者可通过统一的代码操作不同类型数据库,那么如何实现这种统一操作呢?本篇深入JDBC设计思想,用示例代码模拟整个JDBC运行原理。


背景知识:

1.JVM(Java虚拟机)将系统分配的内存区域分为三块(堆区、栈区、方法区)

2.类的加载:当使用new 关键字新建一个对象,或使用Class.forName()加载指定类时,虚拟机读取类(.class)的字节码文件并加载到方法区。<由类加载器完成>

3.类在加载时,静态成员会被执行,包括静态成员被赋值,静态代码块被执行

补充:任何堆区的Java对象都有一个指针指向方法区中的class对象(每个类只有一个),即方法区共享了类的方法。

如以下代码段:

[java] view plain copy
  1. Student s1 = new Student("张三");  
  2.   
  3. s1.study();  
  4.   
  5. Student s2 = new Student("李四");  
  6.   
  7. s2.study();  

程序执行流程:

1.程序经过编译后,.java文件转换成字节码.class文件

2.执行Student s1 = new Student("张三");时:

    a.JVM读取Student类的字节码文件并加载到方法区,生成class对象;

    b.然后在堆区开辟内存区域初始化Student("张三")对象,该对象有一个指针指向方法区中的class对象;

    c.在栈区分配一个变量s1,s1指向堆区Student("张三")对象的首地址;

3.执行s1.study();时,JVM通过堆区s1对象指向方法区的指针,找到class对象的方法并执行

4.执行Student s2 = new Student("李四");时,不会再加载并生成class对象(再次强调:同一个类只有一个class对象在方法区),但在堆区和栈区的操作同s1一样

图示如下:



接下来,我们来看看JDBC是如何实现对数据库的统一操作的

实现步骤:

1.sun公司制定标准接口

2.数据库厂商实现标准接口,并封装在定制的驱动文件中

3.开发者通过各厂商驱动文件对不同数据库操作


设计思想关键词:接口、类加载器、静态代码块

设计描述:

1.sun公司制定接口标准:Connection接口和DriverManager类(Connection接口提供操作数据库的抽象方法,待数据库厂商实现;DriverManager类提供给数据库厂商注册连接和获取连接的方法) 。

2.数据库厂商实现Connection接口中的方法(用来定义具体的数据库操作)

3.数据库厂商自定义驱动文件Driver类,将2中的连接注册到SUN提供的DriverManager中(此过程在静态代码块中,确保类被加载时即可执行)

4.程序员通过Class.for("");加载驱动文件,并获取连接,进而对数据库进行操作


示意图:



SUN公司

首先,SUN公司定义了一个接口类:

[java] view plain copy
  1. /** 
  2.  * @Description:sun公司定义的接口类 
  3.  * 
  4.  * @author:SUN 
  5.  */  
  6. public interface Connection {  
  7.   
  8.     public void f1();  
  9. }  

同时,SUN公司定义了一个驱动管理类:

[java] view plain copy
  1. /** 
  2.  * @Description:SUN公司定义的驱动管理类 
  3.  * 
  4.  * @author:SUN 
  5.  */  
  6. public class DriverManager {  
  7.   
  8.     public static Connection conn = null;  
  9.   
  10.     /** 
  11.      * 注册连接 
  12.      * 
  13.      * @param connection 
  14.      */  
  15.     public static void registConnection(Connection connection) {  
  16.         conn = connection;  
  17.     }  
  18.   
  19.     /** 
  20.      * 获取连接 
  21.      * 
  22.      * @return 
  23.      */  
  24.     public static Connection getConnection() {  
  25.         return conn;  
  26.     }  
  27. }  

数据库厂商:(如Oracle、MySQL等)

各数据库厂商实现SUN制定的接口标准,如:

Oracle

[java] view plain copy
  1. /** 
  2.  * @Description:Oracle数据库厂商实现的接口类 
  3.  * 
  4.  * @author:Oracle 
  5.  */  
  6. public class ConnectionOracleImpl implements Connection {  
  7.   
  8.     @Override  
  9.     public void f1() {  
  10.         // 这里实现Oracle操作数据库的具体方法,封装在.jar文件中,供程序员调用  
  11.         System.out.println("Oracle的f1()方法实现");  
  12.     }  
  13.   
  14. }  

或者MySQL

[java] view plain copy
  1. /** 
  2.  * @Description:MySQL数据库厂商实现的接口类 
  3.  * 
  4.  * @author:MySQL 
  5.  */  
  6. public class ConnectionMySQLImpl implements Connection {  
  7.   
  8.     @Override  
  9.     public void f1() {  
  10.         //这里实现MySQL操作数据库的具体方法,封装在.jar文件中,供程序员调用  
  11.         System.out.println("MySQL的f1()方法实现");  
  12.     }  
  13.   
  14. }  

同时,数据库厂商定制自己的驱动类,并通过静态代码块,确保该驱动类被加载时,SUN的驱动管理类可以注册厂商的数据库连接,如:

Oracle

[java] view plain copy
  1. /** 
  2.  * @Description:Oracle厂商制定的驱动类 
  3.  * 
  4.  * @author:Oracle 
  5.  */  
  6. public class OracleDriver {  
  7.     static {  
  8.         DriverManager.registConnection(new ConnectionOracleImpl());  
  9.     }  
  10. }  

或者MySQL

[java] view plain copy
  1. /** 
  2.  * @Description:MySQL厂商制定的驱动类 
  3.  * 
  4.  * @author:MySQL 
  5.  */  
  6. public class MySQLDriver {  
  7.     static {  
  8.         DriverManager.registConnection(new ConnectionMySQLImpl());  
  9.     }  
  10. }  

开发者:

开发人员引入某个数据库厂商的驱动文件,即可调用内部方法操作数据库,如:

[java] view plain copy
  1. /** 
  2.  * @Description:开发人员 
  3.  * 
  4.  * @author:me 
  5.  */  
  6. public class Test2 {  
  7.   
  8.     public static void main(String[] args) throws Exception {  
  9.         Class.forName("test.OracleDriver");// 虚拟机根据类名找到字节码文件  
  10.         Connection con = DriverManager.getConnection();  
  11.         con.f1();  
  12.   
  13.         Class.forName("test.MySQLDriver");// 虚拟机根据类名找到字节码文件  
  14.         Connection con2 = DriverManager.getConnection();  
  15.         con2.f1();  
  16.     }  
  17. }  

运行结果:

Oracle的f1()方法实现
MySQL的f1()方法实现


转载请注明出处:

http://blog.csdn.NET/daijin888888/article/details/50969621


1 0
原创粉丝点击