JDBC数据库驱动及原理 您所在的位置:网站首页 说说数据库的使用 JDBC数据库驱动及原理

JDBC数据库驱动及原理

2024-06-15 22:45| 来源: 网络整理| 查看: 265

前言

JDBC即Java DataBase Connectivity,java数据库连接;JDBC 提供的API可以让JAVA通过API方式访问关系型数据库,执行SQL语句,获取数据;常见关系型数据库如Oracle、MySQL、SQLServer等;对于非关系型数据库如Redis、mongonDB等就显得无力;关系型数据库最典型的数据结构是表,易于维护,灵活使用(使用表结构,支持SQL语言的简单及复杂表及多表之间的查询),非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合(文档型、键值对型、列式数据库、图形数据库),相对于关系型数据库(读写性能比较差,效率低,灵活度低、高并发处理显得鸡肋);非关系型数据库优点多多,速度快、高拓展、低成本(就数据结构复杂,其他都比较简单,学习难度就有点大)。 言归正传,从根本来讲,JDBC是一种规范,它提供的接口,是一套完整的、可移植的访问底层数据库的程序。

JDBC驱动结构模型

分两种架构模型:三层和两层;下面是三层软件架构的模型,分别是表示层UI、业务逻辑层BLL、数据访问层DAL;两层架构的就把表现层UI拿掉。

JDBC驱动结构模型

java中使用JDBC连接数据库

在应用程序中进行数据库连接,调用JDBC接口,首先要将特定厂商的JDBC驱动实现加载到系统内存中,然后在应用程序中就可以直接根据URL和用户密码来识别获取对应的驱动实例,与数据库建立连接,对数据库进行相关操作。

//1.加载mysql数据库驱动 static String driverName = "com.mysql.jdbc.Driver"; //2.加载oracle数据库驱动 //static String driverName = "oracle.jdbc.driver.OracleDriver"; //3.加载SQL Server数据库驱动 //static String driverName = "com.microsoft.sqlserver.jdbc.SQLServerDriver"; static String url = "jdbc:mysql://127.0.0.1:3306/mysql"; static String username = "root"; static String password = "123456"; public void getConnection() { try { // 1.1、加载驱动,使用Class.forName()将驱动类加载到内存 Class.forName(driverName); //1.2或者使用 //Driver driver = (Driver) Class.forName(driverName).newInstance(); // 2.1、获取connection Connection conn = DriverManager.getConnection(url,username,password); //2.2或者使用 /* Properties info = new Properties(); info.put("user", username); info.put("password", password); Connection conn = driver.connect(url, info); */ System.out.println(conn); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } } JDBC驱动原理详解

对于已经安装好的数据库之后,我们想要直接使用数据库,比如保存用户数据资料等,要通过该数据库厂商提供的驱动程序才能与数据库交互,其实就是数据库厂商的JDBC接口实现;我们只需使用他们提供的对JDBC接口实现类的jar文件。如Oracle数据库对应使用ojdbc8.jar包等等。不同关系型数据库版本使用的JDBC的jar包都不同。 1.上面加载的JDBC驱动的方法有两种,一种使用DriverManager管理(推荐),一种直接Driver(耦合太强,不推荐) 1.1 Class.forName(driverName)和Driver driver = (Driver) Class.forName(driverName).newInstance(); 因为驱动本质就是一个class,Class.forName()的作用就是将class加载到内存中,而这个driveName其实就是实现了java.sql.Driver(在java.lang.Object包下找到)接口的类(此类可以在数据库厂商提供的JDBC jar包中找到);当使用Class.forName(driverName)加载驱动类到内存中的时候,同时会执行这个驱动类中的静态代码块,创建一个Driver实例,然后调用DriverManager.registerDriver(Driver实例)进行驱动注册,供后面使用。 下面使用oracle数据库为例来源码分析: 1.1.1在oracle.jdbc.driver包下的OracleDriver驱动类,实现了java.sql.Driver类 在这里插入图片描述 1.1.2当使用Class.forName()加载驱动类oracle.jdbc.driver.OracleDriver.class的时候,会执行oracle.jdbc.driver.OracleDriver.class中的静态代码块和java.sql.DriverManager.class中的静态代码块:

//oracle.jdbc.driver.OracleDriver.class中的静态代码块 package oracle.jdbc.driver; import java.security.AccessController; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import oracle.jdbc.OracleDatabaseMetaData; import oracle.jdbc.driver.OracleDriver.1; import oracle.security.pki.OracleSecretStore; import oracle.security.pki.OracleWallet; public class OracleDriver implements Driver { private static OracleDriver defaultDriver = null; private static final String _Copyright_2004_Oracle_All_Rights_Reserved_; //省略。。。 static { Timestamp localTimestamp = Timestamp.valueOf("2000-01-01 00:00:00.0"); try { if (defaultDriver == null) { //1.不存在OracleDriver驱动实例就创建该实例--自己加的注释 defaultDriver = new OracleDriver(); //2.将Oracle驱动实例进行注册--自己加的注释 DriverManager.registerDriver(defaultDriver); } } catch (RuntimeException localRuntimeException) { ; } catch (SQLException localSQLException) { ; } _Copyright_2004_Oracle_All_Rights_Reserved_ = null; } } // java.sql.DriverManager.class中的静态代码块 package java.sql; import java.util.Iterator; import java.util.ServiceLoader; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.concurrent.CopyOnWriteArrayList; import sun.reflect.CallerSensitive; import sun.reflect.Reflection; public class DriverManager { // List of registered JDBC drivers private final static CopyOnWriteArrayList 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; // Used in println() to synchronize logWriter private final static Object logSync = new Object(); /* Prevent the DriverManager class from being instantiated. */ private DriverManager(){} /** * Load the initial JDBC drivers by checking the System property * jdbc.properties and then use the {@code ServiceLoader} mechanism */ static { //加载配置在jdbc.drivers系统变量中的驱动driver--自己的注释 loadInitialDrivers(); println("JDBC DriverManager initialized"); } private static void loadInitialDrivers() { String drivers; try { drivers = AccessController.doPrivileged(new PrivilegedAction() { public String run() { return System.getProperty("jdbc.drivers"); } }); } catch (Exception ex) { drivers = null; } // If the driver is packaged as a Service Provider, load it. // Get all the drivers through the classloader // exposed as a java.sql.Driver.class service. // ServiceLoader.load() replaces the sun.misc.Providers() AccessController.doPrivileged(new PrivilegedAction() { public Void run() { ServiceLoader loadedDrivers = ServiceLoader.load(Driver.class); Iterator driversIterator = loadedDrivers.iterator(); /* Load these drivers, so that they can be instantiated. * It may be the case that the driver class may not be there * i.e. there may be a packaged driver with the service class * as implementation of java.sql.Driver but the actual class * may be missing. In that case a java.util.ServiceConfigurationError * will be thrown at runtime by the VM trying to locate * and load the service. * * Adding a try catch block to catch those runtime errors * if driver not available in classpath but it's * packaged as service and that service is there in classpath. */ try{ while(driversIterator.hasNext()) { driversIterator.next(); } } catch(Throwable t) { // Do nothing } return null; } }); println("DriverManager.initialize: jdbc.drivers = " + drivers); if (drivers == null || drivers.equals("")) { return; } String[] driversList = drivers.split(":"); println("number of Drivers:" + driversList.length); for (String aDriver : driversList) { try { println("DriverManager.Initialize: loading " + aDriver); Class.forName(aDriver, true, ClassLoader.getSystemClassLoader()); } catch (Exception ex) { println("DriverManager.Initialize: load failed: " + ex); } } } }

当使用Class.forName(driverName)加载驱动类到内存中的时候,同时会执行这个驱动类中的静态代码块,创建一个Driver实例;然后调用DriverManager 进行注册Driver;DriverManager 作为 Driver 的管理器,它在第一次被调用的时候,它会被加载到内存中,然后执行其定义的static静态代码段,在静态代码段中,有一个 loadInitialDrivers() 静态方法,用于加载配置在jdbc.drivers 系统属性内的驱动Driver,配置在jdbc.drivers 中的驱动driver将会首先被加载上面的静态代码块使用的是DriverManager来统一管理操作Driver和获取Connection对象;DriverManager驱动管理类方便管理存在多个Driver驱动实例的情况;可以进行注册和删除加载的驱动程序,可以根据给定的Url获取符合url协议的驱动Driver并建立Connection连接,进行数据交互。 java.sql.DriverManager类的方法摘要: 在这里插入图片描述 DriverManager.registerDriver(Driver driver)的参数是一个java.sql.Driver接口的实现类实例对象, java.sql.Driver接口的方法摘要有: 在这里插入图片描述 1.2使用DriverManager获取Connection时,使用DriverManager提供的getConnection()方法,该方法会自动根据url匹配对应的驱动Driver实例,然后调用Driver实例实现java.sql.Driver接口方法connect()获取对应的URL的数据库连接,返回Connection对象实例;如果不使用DriverManager可以直接Driver实例调用java.sql.Driver接口的connect(String url,Properties info)方法获取连接。如上面代码两者是等价的

//加载JDBC驱动 Class.forName(driverName); //获取数据库连接 Connection conn = DriverManager.getConnection(url,username,password);

跟下面是一样的效果:

//获取JDBC驱动 Driver driver = (Driver) Class.forName(driverName).newInstance(); //或者Driver driver = DriverManager.getDriver(url); Properties info = new Properties(); info.put("user", username); info.put("password", password); //获取数据库链接 Connection conn = driver.connect(url, info);

1.3获取数据库时的认证 利用Driver的接口方法acceptsURL(String url) ,该方法只会校验url是否符合协议和是否能打开该url连接,每个数据库厂商都会制定自己的url协议,只有符合自己的协议形式的url才认为自己能够打开这个url;但不会判断url是否有效。 例如oracle定义的自己的url协议如下: jdbc:oracle:thin:@//:/ServiceName jdbc:oracle:thin:@:: oracle的acceptsURL(String url)方法源码如下:

package oracle.jdbc.driver; import java.security.AccessController; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; import java.sql.DriverPropertyInfo; import java.sql.SQLException; import java.sql.Timestamp; import java.util.Enumeration; import java.util.Hashtable; import java.util.Properties; import oracle.jdbc.OracleDatabaseMetaData; import oracle.jdbc.driver.OracleDriver.1; import oracle.security.pki.OracleSecretStore; import oracle.security.pki.OracleWallet; public class OracleDriver implements Driver { //省略。。。 public boolean acceptsURL(String var1) { if (var1.startsWith("jdbc:oracle:")) { return this.oracleDriverExtensionTypeFromURL(var1) > -2; } else { return false; } } private int oracleDriverExtensionTypeFromURL(String var1) { int var2 = var1.indexOf(58) + 1; if (var2 == 0) { return -2; } else { int var3 = var1.indexOf(58, var2); if (var3 == -1) { return -2; } else if (!var1.regionMatches(true, var2, "oracle", 0, var3 - var2)) { return -2; } else { ++var3; int var4 = var1.indexOf(58, var3); if (var4 == -1) { return -3; } else { String var5 = var1.substring(var3, var4); if (var5.equals("thin")) { return 0; } else { return !var5.equals("oci8") && !var5.equals("oci") ? -3 : 2; } } } } } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有