注册mySQL到JDBC驱动程序方法浅谈
一、注册方法(4种)
1)服务提供者框架:
符合JDBC 4.0规范的驱动程序包含了一个文件META-INF/services/java.sql.Driver,在这个文件中提供了JDBC驱动实现的类名。
例如:mysql-connector-java-5.1.40-bin.jar文件中就可以找到java.sql.Driver文件,用文本编辑器打开文件就可以看到:com.mysql.jdbc.Driver类。
JVM的服务提供者框架在启动应用时就会注册服务,例如:mySQL的JDBC驱动就会被注册,而原代码中的Class.forName("com.mysql.jdbc.Driver")仍然可以存在,但是不会起作用。
2)Class.forName("com.mysql.jdbc.Driver");
通过对类com.mysql.jdbc.Driver初始化,执行静态初始化代码,调用DriverManager注册JDBC驱动。
注:通过setProperty的测试,确认类com.mysql.jdbc.Driver也没有加载,那么静态初始化代码肯定被执行了,但是如果服务提供者框架已经注册的服务,这里注册会失败,编程的预期是这样的,可是理论上DriverManager.registerDriver可以重复注册的,为什么这里不能重复注册呢?
3)System.setProperty("jdbc.drivers", "com.mysql.jdbc.Driver";);
设置JVM的系统属性,当JVM第一次加载DriverManager类时,会执行类的静态初始化代码,代码中调用loadInitialDrivers()方法,就会加载设置的属性对应的类,执行类的静态初始化代码完成注册。
注:因为注册的机制无法深入理解,只知道没有加载过的类可以注册成功,加载过的就不能重复注册了。
注:setProperty必须在DriverManager第一次运行前才有效,说明”服务提供者”框架注册服务时并没有加载类,因为一旦加载类就会执行类的静态初始化代码,那么注册JDBC驱动就一定会调用DriverManager类的静态初始化代码,那么setProperty就会失效,所以说明注册服务是不加载类的。
4)DriverManager.registerDriver(new com.mysql.jdbc.Driver());
其实前面的2)和3)最终都是通过这个方法注册的,但是这个方法就可以重复注册。
注:对于重复注册后,建立链接时使用哪个驱动我就不明白了,可以取消注册,取消的关键字是基于创建的对象的,所以就算重名也不会出错。
注:这种注册方式没有前面几种好,因为这种注册方式会在代码中与需要注册的驱动程序的类绑定,前面都可以通过配置参数实现注册。
二、各自特点:
1)全自动。只要提供符合规范的JAR文件就可以了。
2)利用反射机制,将驱动类注入到代码中,不需要与代码绑定。
3)基于系统的属性设置方法,将驱动类注入到代码中,但是好像只能绑定一个JDBC驱动。
4)最终的注册机制。会出现重复注册,但是好像对程序没影响,还需要与代码绑定,驱动变了,必须修改代码,维护成本过高,当然也是灵活性最好,管理最方便的。
以下是测试代码:
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration; /**
* @author 朱远翔.Tom 测试JDBC驱动注册
*/
public class JDBCDriverTest { public static void main(String[] args) {
Driver aDriver;
Connection connection;
Enumeration em;
// “org.gjt.mm.mysql.Driver”是“com.mysql.jdbc.Driver”的子类,其构造函数就是调用父类的构造函数。
String driverString = "com.mysql.jdbc.Driver";
// String driverString = "org.gjt.mm.mysql.Driver";
String url = "jdbc:mysql://localhost/ElectricalStore?useSSL=false";
String username = "admin";
String password = "123456"; try {
// 将DriverManager的日志流输出到Console窗口中,方便监控
// DriverManager.setLogStream(System.out);
// DriverManager.println("------DriverManager logs start!------"); // 只是设置了一个JVM的系统属性,并不建立JDBC驱动程序。
// 建立JDBC驱动是依赖系统第一次调用DriverManager类时,执行了这个类的静态初始化代码中的loadInitialDrivers(),
// 加载驱动的方法会把设置的jdbc.drivers属性对应的驱动类通过DriverManager.registerDriver注册到JDBC中。
// 因此,必须放在DriverManager被第一次调用之间,也就是需要将前面那两行代码注释掉
System.out.println("1.1> Tried to use setProperty.");
System.setProperty("jdbc.drivers", driverString);
System.out.println("---List of all jdbc drivers---");
em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("There is no JDBC drivers");
} else {
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
}
} System.out.println("1.2> we tried to use Class.forName");
// Class.forName(driverString)在JavaSE 6.0后符合JDBC 4.0规范的驱动可以不用
// 基于服务提供机制( Service Provider mechanism),
// 系统会自动搜索mysql-connector-java-???-bin.jar中的META-INF/services/java.sql.Driver
// 这个文件会包含mysql jdbc驱动程序的入口:com.mysql.jdbc.Driver
// 应用程序调用Class.forName()也不会出错,只是什么都不会执行。
// 因为Class.forName()就是执行静态初始化代码,已经初始化过的类就无法激活这段代码了
// System.setProperty("jdbc.drivers",driverString);与Class.forName()一样。
try {
Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver");
} catch (ClassNotFoundException e) {
System.out.println("Driver not found");
} System.out.println("---List of all jdbc drivers---");
em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("There is no JDBC drivers");
} else {
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
}
} System.out.println("1.3> we tried to use DriverManager.registerDriver");
// 手工注册mySQL的JDBC驱动程序,也就出现了与mySQL绑定过紧的问题,如果以后需要更换驱动,就需要修改代码。
// 系统容许出现重复注册同样的jdbc驱动类
DriverManager.registerDriver(new com.mysql.jdbc.Driver());
DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver());
DriverManager.registerDriver(new com.mysql.jdbc.Driver()); System.out.println("---List of all jdbc drivers---");
em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
} System.out.println("<1.5> Deregister all JDBC drivers");
em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
DriverManager.deregisterDriver(aDriver); // 将已经注册的驱动程序取消注册
} em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("2.1> Now, there is no JDBC driver");
} System.out.println("2.2> we tried to use Class.forName again");
try {
Class.forName(driverString);
} catch (ClassNotFoundException e) {
System.out.println("Driver not found");
}
try {
Class.forName("com.mysql.fabric.jdbc.FabricMySQLDriver");
} catch (ClassNotFoundException e) {
System.out.println("Driver not found");
}
try {
Class.forName(driverString);
} catch (ClassNotFoundException e) {
System.out.println("Driver not found");
} em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("There is no JDBC drivers");
} else {
System.out.println("---List of all jdbc drivers---");
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
}
} System.out.println("2.3> we tried to use setProperty again");
System.setProperty("jdbc.drivers", "com.mysql.fabric.jdbc.FabricMySQLDriver"); em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("There is no JDBC drivers");
} else {
System.out.println("---List of all jdbc drivers---");
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
}
} System.out.println("2.3> Tried to use DriverManager.registerDriver again"); DriverManager.registerDriver(new com.mysql.jdbc.Driver());
DriverManager.registerDriver(new com.mysql.fabric.jdbc.FabricMySQLDriver());
DriverManager.registerDriver(new com.mysql.jdbc.Driver()); System.out.println("---List of all jdbc drivers---");
em = DriverManager.getDrivers(); // 获取已加载JDBC驱动程序的Enumeration
if (!em.hasMoreElements()) {
System.out.println("There is no JDBC drivers");
} else {
while (em.hasMoreElements()) {
aDriver = (Driver) em.nextElement();
System.out.println(aDriver);
}
} System.out.print("3.1> Tried to establish a connection: ");
connection = DriverManager.getConnection(url, username, password);
System.out.println(connection);
} catch (SQLException e) {
System.out.println("Cannot registered the mysql jdbc driver");
} System.out
.println("jdbc.drivers property: " + System.getProperty("jdbc.drivers", "nothing")); } }
注册mySQL到JDBC驱动程序方法浅谈的更多相关文章
- JavaScript中toStirng()与Object.prototype.toString.call()方法浅谈
toStirng()与Object.prototype.toString.call()方法浅谈 一.toString()是一个怎样的方法?它是能将某一个值转化为字符串的方法.然而它是如何将一个值从一种 ...
- Linux CentOS下MySQL的安装配置之浅谈
前期必备安装:VMware虚拟机,CentOS镜像[注意:Linux下使用CentOS MySQL是不用在官网下载的,只需要配置就OK了] 下面开始正式操作: //CentOS安装MySQL之浅谈 ...
- Android事件侦听器回调方法浅谈
http://developer.51cto.com/art/201001/180846.htm Android事件侦听器作为视图View类的接口,其中包含有不少回调方法,比如:onClick():o ...
- MySQL 优化、设计规则浅谈
当数据量大,数据库相应慢时都会针对数据库进行优化.这时都是要针对具体情况,具体业务需求进行优化的. 但是有些步骤和规则应该适合各种情况的.这里综合网上找的资料简单分析一下. 第一优化你的sql和索引: ...
- toStirng()与Object.prototype.toString.call()方法浅谈
一.toString()是一个怎样的方法?它是能将某一个值转化为字符串的方法.然而它是如何将一个值从一种类型转化为字符串类型的呢? 通过下面几个例子,我们便能获得答案: 1.将boolean类型的值转 ...
- C#使用IHttpModule接口修改http输出的方法浅谈
一.但你每次请求浏览一个页面,比如Login.aspx的时候,都会执行配置文件中system.webserver内的model这个节点的东西(这个是属于遍历的逻辑执行,会将model这个节点的东西全部 ...
- Object.prototype.toString.call()方法浅谈
使用Object.prototype上的原生toString()方法判断数据类型,使用方法如下: Object.prototype.toString.call(value) 1.判断基本类型: Obj ...
- Android中SQLiteOpenHelper类的onUpgrade方法浅谈
public abstract void onUpgrade(SQLiteDatabase db,int oldVersion,int new Version) 这个方法在实现时需要重写. onUpg ...
- 【C#】扩展方法浅谈
C#3 引入的扩展方法这一个理念. 扩展方法最明显的特征是在方法参数中第一个参数有this声明. 其实C#库中有很多已经是扩展方法了.比如linq中对序列使用的查询语句, where, select等 ...
随机推荐
- Docker在Linux上运行NetCore系列(四)使用私有Nuget与多个本地包引用运行ASPNetCore
转发请注明此文章作者与路径,请尊重原著,违者必究. 本篇文章演示了使用Dockerfile在Linux(ubuntu16.04)系统上构建ASPNetCore应用,并且在一个解决方案中存在多个项目之间 ...
- 开发谷歌浏览器插件会上瘾,搞了一个JSONViewer,一个页面格式化多条JSON,提升工作效率
最近写了一个谷歌浏览器插件(Chrome extension),拿出来分享下,希望能提升大家的工作效率. 一.背景 先说痛点:日常开发中,经常需要不停的把接口输出的JSON拷贝到在线JSON格式化页面 ...
- C#开发微信公众平台-就这么简单(附Demo)转载
C#开发微信公众平台-就这么简单(附Demo) 来源:https://www.cnblogs.com/xishuai/p/3625859.html#!comments 写在前面 阅读目录: 服务号和 ...
- D. GukiZ and Binary Operations(矩阵+二进制)
D. GukiZ and Binary Operations We all know that GukiZ often plays with arrays. Now he is thinking ...
- Elasticsearch系列(1):认识Elasticsearch
官方定义 Elasticsearch 是一个实时的分布式搜索分析引擎, 它能让你以一个之前从未有过的速度和规模,去探索你的数据. 它被用作全文检索.结构化搜索.分析以及这三个功能的组合. Elasti ...
- 清除float影响
条件: 父元素中有子元素float的话,可能就会影响父元素的高度,从而影响布局: 解决方案: 1.直接给父元素定高: 弊端:必须知道父元素的高: 2. 父元素使用overflow属性值为hidden解 ...
- 如何实现JavaScript的Map和Filter函数?
译者按: 鲁迅曾经说过,学习JavaScript最好方式莫过于敲代码了! 原文: Master Map & Filter, Javascript’s Most Powerful Array F ...
- jquery中each中使用break和continue
在jquery中each中直接使用break或者continue会提示:必须在循环中使用.会报错不能直接使用. 但是,是不是就不能用呢,答案是的,但是换种方法可以达到相同的效果: 可以只用return ...
- form表单基础知识
form 元素是块级元素 ------------------- ------------------- ----------------------------------------------- ...
- 二进制安装 kubernetes 1.12(一) - 安装 ETCD
软件环境 软件 版本 操作系统 CentOS 7.4 Docker 18-ce Kubernetes 1.12 服务器角色 角色 IP 组件 k8s-master 192.168.0.205 kube ...