使用JDBC进行数据库操作的第一步就是驱动注册(当然你得先导入JAR)。
驱动注册有多种方式,第一步必然是获得正确的驱动名称与URL格式

驱动名称与URL格式

RDBMS 驱动程序名称       
URL格式
MySQL com.mysql.jdbc.Driver       
jdbc:mysql://hostname/databaseName
ORACLE oracle.jdbc.driver.OracleDriver       
jdbc:oracle:thin:@hostname:portNumber:databaseName
PostgreSQL org.postgresql.Driver jdbc:postgresql://hostname:port/dbname
DB2 com.ibm.db2.jdbc.net.DB2Driver jdbc:db2:hostname:port Number/databaseName
Sybase com.sybase.jdbc.SybDriver jdbc:sybase:Tds:hostname: portNumber/databaseName
 
常用的驱动程序名称与URL格式如上表所示,随着版本变化,会存在些许变动,如有不对,还需重新查验
比如MYSQL中5与6 ,mysql5用的驱动是com.mysql.jdbc.Driver,mysql6以后用的是com.mysql.cj.jdbc.Driver

MYSQL的驱动下载

MYSQL的connector下载地址
https://dev.mysql.com/downloads/connector/
另外还有完整的文档

oracle驱动下载

https://www.oracle.com/technetwork/database/application-development/jdbc/downloads/index.html

驱动注册

在通过驱动管理器创建连接前需要进行驱动注册
驱动注册有三种形式
    Class.forName("com.mysql.jdbc.Driver");
    DriverManager.registerDriver(new com.mysql.jdbc.Driver());
    System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver");
 
可以查看mysql-connector中的源码
package com.mysql.jdbc;

import java.sql.SQLException;

public class Driver extends NonRegisteringDriver implements java.sql.Driver {

//

// Register ourselves with the DriverManager

//

static {

try {

java.sql.DriverManager.registerDriver(new Driver());

} catch (SQLException E) {

throw new RuntimeException("Can't register driver!");

}

}

/**

* Construct a new driver and register it with DriverManager

*

* @throws SQLException

* if a database error occurs.

*/

public Driver() throws SQLException {

// Required for Class.forName().newInstance()

}

}
类加载时,会执行<clinit>方法,在jvm第一次加载class文件时调用,包括静态变量初始化语句和静态块的执行 。
所以Class.forName("com.mysql.jdbc.Driver");会调用java.sql.DriverManager.registerDriver(new Driver());  完成了驱动的注册
所以直接调用java.sql.DriverManager.registerDriver(new Driver()); 也是可以的
 
驱动管理器类加载时,也会从系统属性"jdbc.drivers" 中获取数据
所以,在驱动管理器加载之前,可以使用    System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver"); 进行设置
也可以同时设置多个比如System.setProperty("jdbc.drivers","XXXDriver:XXXDriver:XXXDriver");
 
  • DriverManager.registerDriver(new com.mysql.jdbc.Driver());  依赖具体,没有面向抽象编程,不推荐
  • System.setProperty("jdbc.drivers","com.mysql.jdbc.Driver"); DriverManager加载前有用,不够灵活方便
  • Class.forName("com.mysql.jdbc.Driver"); 通常使用

自动加载的4.0时代

从JDBC4.0开始,就不在需要主动的显式加载,对应JDK6
在调用 getConnection 方法时,DriverManager 会试着从初始化时加载的那些驱动程序以及使用与当前 applet 或应用程序相同的类加载器显式加载的那些驱动程序中查找合适的驱动程序。
 
JDBC 4.0 的规范规定,所有 JDBC 4.0 的驱动 jar 文件必须包含一个 java.sql.Driver,它位于 jar 文件的 META-INF/services 目录下。这个文件里每一行便描述了一个对应的驱动类
在启动项目或是服务时,会判断当前classspath中的所的jar包,并检查他们META-INF目录下,是否包含services文件夹,如果包含,就会将里面的配置加载成相应的服务。
META-INF/services/jdbc.sql.Driver文件内容为需要加载的驱动,如下图所示
可以打印出所有的已经加载的驱动程序,如下图所示,与上图文件中的不谋而合
 
所以,对于4.0前,使用Class.forName
4.0后我们只需要将JAR包管理好就足够了,这一切都会有人帮我们完成(当然前提是需要使用配套的驱动Jar包)
 
完整的loadInitialDrivers方法
private static void loadInitialDrivers() {

String drivers;

try {

//获取环境变量中jdbc.drivers的列表

drivers = AccessController.doPrivileged(new PrivilegedAction<String>() {

public String run() {

return System.getProperty("jdbc.drivers");

}

});

} catch (Exception ex) {

drivers = null;

}

//如果按照规范在jar包中的META-INF/services设置了文件,将会加载为服务

// 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<Void>() {

public Void run() {

ServiceLoader<Driver> loadedDrivers = ServiceLoader.load(Driver.class);

Iterator<Driver> 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);

}

}

}
简言之,loadInitialDrivers主要做了两件事情:
  • 读取系统属性jdbc.drivers,如果为空就拉到,如果存在将会进行加载。
  • 检查jar包中的META-INF/services,如果有那么会自动注册,服务注册依赖的是ServiceLoader
 
对于加载的驱动程序,在前面已经说过,静态代码块中,会完成注册,而注册就是添加到CopyOnWriteArrayList<DriverInfo> registeredDrivers中
 

总结

驱动注册就是加载数据库的驱动程序,是使用JDBC进行数据库操作的第一步。
JDBC的桥接模式,提供给应用程序开发者的API是抽象,这个驱动程序就是实现,如果不能进行成功注册,就没办法提供后续的服务了,所以驱动注册很重要。
以 JDBC4.0为分水岭
如果按照JDBC4.0后的规范,在jar包中设置了META-INF/services/jdbc.sql.Driver文件,并且写入了驱动,那么会自动加载
如果是之前的,则需要使用Class.forName()进行显式加载。
自动加载依赖ServiceLoader.load(Driver.class);,其中关于目录的设置是写死的PREFIX = "META-INF/services/",想要深入研究可以翻阅ServiceLoader
 
 

JDBC驱动程序注册 JDBC简介(二)的更多相关文章

  1. JDBC驱动程序类型

    JDBC驱动程序是什么? JDBC驱动程序在JDBC API中实现定义的接口,用于与数据库服务器进行交互. 例如,使用JDBC驱动程序,可以通过发送SQL或数据库命令,然后使用Java接收结果来打开数 ...

  2. JDBC驱动程序分类

    JDBC驱动程序分类 JDBC驱动程序:各个数据库厂商根据JDBC的规范制作的 JDBC 实现类的类库 JDBC驱动程序总共有四种类型: 第一类:JDBC-ODBC桥. 第二类:部分本地API部分Ja ...

  3. 注册mySQL到JDBC驱动程序方法浅谈

    一.注册方法(4种) 1)服务提供者框架: 符合JDBC 4.0规范的驱动程序包含了一个文件META-INF/services/java.sql.Driver,在这个文件中提供了JDBC驱动实现的类名 ...

  4. 注册Jdbc驱动程序的三种方式

    注册Jdbc驱动程序的三种方式 1. Class.forName("com.mysql.jdbc.Driver"); 2. DriverManager.registerDriver ...

  5. 注册jdbc驱动的三种方式

    java.sql.DriverManger类简介   java的驱动管理类.管理一组 JDBC 驱动程序. javax.sql.DataSource 接口是 JDBC 2.0 API 中的新增内容,它 ...

  6. JDBC设计理念浅析 JDBC简介(一)

    概念 JDBC是J2EE的标准规范之一,J2EE就是为了规范JAVA解决企业级应用开发制定的一系列规范,JDBC也不例外. JDBC是用于Java编程语言和数据库之间的数据库无关连接的标准Java A ...

  7. 使用JDBC驱动程序处理元数据

    使用 JDBC 驱动程序处理元数据 一.前言 Java 通过JDBC获得连接以后,得到一个Connection 对象,可以从这个对象获得有关数据库管理系统的各种信息,包括数据库中的各个表,表中的各个列 ...

  8. jmeter使用jdbc获取注册验证码进行注册

    自动化工具测试注册功能时,往往会遇到验证码,这个烦人的验证码怎么能够解决掉呢? 通常有两种方法 让开发禁用注册码,或在测试环境写个固定的验证码 在jmeter中用 jdbc获取数据库中验证码 今天通过 ...

  9. 使用 JDBC 驱动程序

    本部分提供使用 Microsoft JDBC Driver for SQL Server 与 SQL Server 数据库建立简单连接的快速入门指导.在连接到 SQL Server 数据库之前,必须首 ...

随机推荐

  1. 编程菜鸟的日记-初学尝试编程-C++ Primer Plus 第6章编程练习6

    #include <iostream> #include <string> using namespace std; const int MSIZE=100; struct j ...

  2. H5上传功能

    近期开发一个关于微信公总号二次开发中,上传图片的需求,测试几个开源插件,更新一些心得,有需要可留言!!! plupload plupload多张上传图片的一个参考demo ajaxFileUpload ...

  3. 让数字变化炫酷起来,数字滚动Text组件[Unity]

    让数字滚动起来 上周我的策划又提了样需求,当玩家评分发生变动时,屏幕出现人物评分浮层UI,播放评分数字滚动动画.这类数字滚动需求非常常见,我就按一般思路,将startvalue与endvalue每隔一 ...

  4. mysql爱之深探测

    第一:函数 一:内置函数 MYSQL中提供了很多内置的函数,以下: CHAR_LENGTH(str) 返回值为字符串str 的长度,长度的单位为字符.一个多字节字符算作一个单字符. 对于一个包含五个二 ...

  5. 用Group by分组后,取每组的前3条记录,怎么取?

    使用子查询进行查询 SELECT * FROM home_content a WHERE ( SELECT count(id) FROM home_content WHERE class_link = ...

  6. 【原创】C# API 未能创建 SSL/TLS 安全通道 问题解决

    在调用执行API之前添加以下代码就行了 System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;

  7. 口袋appnabcd

    N(need)需求:依据我们学习经历的情况而言,对于初次接触的专业的学生来说,对学习的方向上会感到迷茫,不知道如何学习以及不知道学什么.比如对于计算机专业来说,对于一些软件的选择和下载,应用环境配置等 ...

  8. 上传文件格式,及headers设置

    file[]:(binary)文件格式,传过去的参数自然是query string parameters  形式,当然也有纯的formData格式 formData格式就是将所有的参数append到p ...

  9. 【.NET Core微服务实战-统一身份认证】开篇及目录索引

    简介 ​ 学习.NETCORE也有1年多时间了,发现.NETCORE项目实战系列教程很少,都是介绍开源项目或基础教程,对于那些观望的朋友不能形成很好的学习思路,遇到问题怕无法得到解决而不敢再实际项目中 ...

  10. Spring Cloud Eureka 使用 IP 地址进行服务注册

    默认情况下,Eureka 使用 hostname 进行服务注册,以及服务信息的显示,那如果我们使用 IP 地址的方式,该如何配置呢?答案就是eureka.instance.prefer-ip-addr ...