JDBC之Driver和DriverMananger

Java和MySQL的关系

java是在内存中运行的,但是Java想要统一天下,那么就不得不涉及到对于数据的处理。

那么内存中数据资源肯定是有限的,那么处理磁盘或者是数据库中的程序就成了问题。

Java早期属于Sun公司,而MySQL作为一个非常优秀的关系型数据库,也被Sun公司看中。

所以Sun公司收购了MySQL,但是因为MySQL分为了CLIENT和SERVER端

CLIENT连接SERVER端,可以发送具体的指令来连接上SERVER,如下所示:

mysql -hlocalhost -uroot -proot -Proot

但是手动使用MySQL自带的客户端,相对于程序来说,是不合适的。所以指定了一套Java能够操作MySQL的规范。

但是随着数据库的产生如雨后春笋般涌出,如Oracle等,那么Java为了抢占市场,也能够操作其他的数据库,而不是只支持自己家的MySQL。

Java制定了一套连接数据库的规范,这就是大名鼎鼎的JDBC。

JDBC

概念:Java Database connect java版本的数据库连接

只有在连接上数据库的条件下,才能够来操作数据库。所以在JDBC中提供出来对应的接口。

JDBC中只是定义如何连接、设置事务、SQL操作等,所以具体的操作,需要由每家数据库厂商提供对应的驱动来进行实现JDBC。

演变过程

那么具体是如何做到的呢?这就是接下来要来进行分析的DriverManager和Driver(驱动)所要做的事情了。

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

驱动加载入内存的过程

这里所谓的驱动,其实就是实现了java.sql.Driver接口的类。如:

Oracle的驱动类是 oracle.jdbc.driver.OracleDriver.class(此类可以在oracle提供的JDBC jar包中找到),此类实现了java.sql.Driver接口。

MySQL的驱动类是com.mysql.cj.jdbc.Driver.class类,此类实现了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.cj.jdbc.Driver"); //加载MySQL 数据库驱动
Class.forName("com.mysql.jdbc.Driver");

注意:Class.forName()将对应的驱动类加载到内存中,然后执行内存中的static静态代码段,代码段中,会创建一个驱动Driver的实例,放入DriverManager中,供DriverManager使用。

Oracle加载驱动的静态方法

例如,在使用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) {
}

MySQL加载驱动的静态方法

在MySQL中,如下所示:

public class Driver extends NonRegisteringDriver implements java.sql.Driver {
public Driver() throws SQLException {
} static {
try {
// 利用DriverManager来加载驱动
DriverManager.registerDriver(new Driver());
} catch (SQLException var1) {
throw new RuntimeException("Can't register driver!");
}
}
}

从上面来看的话,我们加载了Driver,程序就会自动调用DriverManager来自动注册一个驱动到DriverManager中来,由DriverManager来进行管理维护Driver。

利用CopyOnWriteArrayList集合来进行存储Driver(适用于读多写少的情况)

那么Driver到底做了些什么事情呢?

Driver的功能

首先应该想到的是,既然是驱动,就需要来连接数据库,不同厂商提供的数据库有各自的实现方式。

那么既然实现不同,那么就需要来做统一管理,这个时候接口的作用就体现出来了。

因为各个厂商实现方式不同,连接数据库的方式也不同,那么就需要针对性的来做连接。

我们猜测一下:肯定有连接协议方式、账号密码、自定义参数等等信息,Driver都得需要来支持。

首先看下在接口中的定义:java.sql.Driver接口规定了Driver应该具有以下功能:

其中:

acceptsURL

**acceptsURL(String url) ** :用来测试对指定的url,该驱动能否打开这个url连接。driver对自己能够连接的url会针对不同的数据库厂商针对自己的协议来做自定义校验,只有符合自己的协议形式的url才认为自己能够打开这个url,如果能够打开,返回true,反之,返回false;

Oracle校验URL

例如:oracle定义的自己的url协议如下:

jdbc:oracle:thin:@//<host>:<port>/ServiceName

jdbc:oracle:thin:@<host>:<port>:<SID>

Oracle自己的acceptsURL(String url)方法如下:

	public boolean acceptsURL(String paramString) {
if (paramString.startsWith("jdbc:oracle:")) {
return (oracleDriverExtensionTypeFromURL(paramString) > -2);
} return false;
} private int oracleDriverExtensionTypeFromURL(String paramString) {
int i = paramString.indexOf(58) + 1; if (i == 0) {
return -2;
}
int j = paramString.indexOf(58, i); if (j == -1) {
return -2;
}
if (!(paramString.regionMatches(true, i, "oracle", 0, j - i))) {
return -2;
}
++j; int k = paramString.indexOf(58, j); if (k == -1) {
return -3;
}
String str = paramString.substring(j, k); if (str.equals("thin")) {
return 0;
}
if ((str.equals("oci8")) || (str.equals("oci"))) {
return 2;
} return -3;
}

由上可知oracle定义了自己应该接收什么类型的URL,自己能打开什么类型的URL连接(注意:这里acceptsURL(url)只会校验url是否符合协议,不会尝试连接判断url是否有效) 。拓展阅读:常用数据库 JDBC URL格式

MySQL校验URL

例如:mysql定义的自己的url协议如下:

jdbc:mysql://host:port/database?x=xx?y=yy

在MySQL中也有代码来判断:Type.isSupported方法中,用一个枚举的scheme来进行判断,下面摘一段过来:

....
jdbc:mysql:
jdbc:mysql:replication:
....

而对于我们输入的url来说,如:jdbc:mysql://127.0.0.1:3306/tb_test

都是以jdbc:mysql:开头的,所以是符合条件的

connect

connect(String url,Properties info)方法,创建Connection对象,用来和数据库的数据操作和交互,而Connection则是真正数据库操作的开始。

对于MySQL来说,在这里也对URL做了校验

    public java.sql.Connection connect(String url, Properties info) throws SQLException {

        try {
// 针对URL来做协议校验
if (!ConnectionUrl.acceptsUrl(url)) {
return null;
} ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info);
// 根据不同的类型在创建不同类型的数据库连接
switch (conStr.getType()) {
case SINGLE_CONNECTION:
return com.mysql.cj.jdbc.ConnectionImpl.getInstance(conStr.getMainHost()); case FAILOVER_CONNECTION:
case FAILOVER_DNS_SRV_CONNECTION:
return FailoverConnectionProxy.createProxyInstance(conStr); case LOADBALANCE_CONNECTION:
case LOADBALANCE_DNS_SRV_CONNECTION:
return LoadBalancedConnectionProxy.createProxyInstance(conStr); case REPLICATION_CONNECTION:
case REPLICATION_DNS_SRV_CONNECTION:
return ReplicationConnectionProxy.createProxyInstance(conStr); default:
return null;
} } catch (UnsupportedConnectionStringException e) {
// when Connector/J can't handle this connection string the Driver must return null
return null; } catch (CJException ex) {
throw ExceptionFactory.createException(UnableToConnectException.class,
Messages.getString("NonRegisteringDriver.17", new Object[] { ex.toString() }), ex);
}
}

上面注释说的是,如果给定的不是MySQL指定的URL,那么将会返回null,如果是正常的,那么将会加载对应的驱动进行返回。

如果找到了对应的类型,那么将会来创建不同的Connection的实例对象。

手动加载驱动 Driver 并实例化进行数据库操作的例子

Oracle

	public static void driverTest(){
try {
//1.加载oracle驱动类,并实例化
Driver driver = (Driver) Class.forName("oracle.jdbc.driver.OracleDriver").newInstance(); //2.判定指定的URL oracle驱动能否接受(符合oracle协议规则)
boolean flag = driver.acceptsURL("jdbc:oracle:thin:@127.0.0.1:1521:xe");
//标准协议测试
boolean standardFlag1 = driver.acceptsURL("jdbc:oracle:thin:@//<host>:<port>/ServiceName");
boolean standardFlag2 = driver.acceptsURL("jdbc:oracle:thin:@<host>:<port>:<SID>");
System.out.println("协议测试:"+flag+"\t"+standardFlag1+"\t"+standardFlag2); //3.创建真实的数据库连接:
String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe";
Properties props = new Properties();
props.put("user", "louluan");
props.put("password", "123456");
Connection connection = driver.connect(url, props);
//connection 对象用于数据库交互,代码省略。。。。。 } catch (Exception e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} finally{ }
}

MySQL

	public static void driverTest(){
try {
//1.加载oracle驱动类,并实例化
Driver driver = (Driver) Class.forName("com.mysql.cj.jdbc.Driver").newInstance(); //2.判定指定的URL mysql驱动能否接受(符合mysql协议规则 jdbc:mysql:)
boolean flag = driver.acceptsURL("jdbc:mysql://127.0.0.1:3306/tb_test");
//标准协议测试
boolean standardFlag1 = driver.acceptsURL("jdbc:mysql://localhost:3306/database");
boolean standardFlag2 = driver.acceptsURL("jdbc:mysql://localhost/database");
System.out.println("协议测试:"+flag+"\t"+standardFlag1+"\t"+standardFlag2); //3.创建真实的数据库连接:
String url = "jdbc:mysql://127.0.0.1:3306/tb_test";
Properties props = new Properties();
props.put("user", "root");
props.put("password", "root");
Connection connection = driver.connect(url, props);
//connection 对象用于数据库交互,代码省略。。。。。 } catch (Exception e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} finally{ }
}

存在现象,为什么connnect中可以放入url和对应的props呢?

properties是如何解析的?

properties既然要作为连接数据库时作为额外附带参数,如用户名+密码等等,是如何来进行操作的呢?

那么看一下MySQL中是如何操作的?

从com.mysql.cj.jdbc.NonRegisteringDriver#connect找到关键性代码

   public java.sql.Connection connect(String url, Properties info) throws SQLException {

        try {
// 校验URL协议
if (!ConnectionUrl.acceptsUrl(url)) {
return null;
} // 解析url和info信息来组成连接串信息
ConnectionUrl conStr = ConnectionUrl.getConnectionUrlInstance(url, info);
// 省略创建数据库连接代码 } catch (UnsupportedConnectionStringException e) {
// when Connector/J can't handle this connection string the Driver must return null
return null; } catch (CJException ex) {
throw ExceptionFactory.createException(UnableToConnectException.class,
Messages.getString("NonRegisteringDriver.17", new Object[] { ex.toString() }), ex);
}
}

看下com.mysql.cj.conf.ConnectionUrl#getConnectionUrlInstance是如何来判断的?

    public static ConnectionUrl getConnectionUrlInstance(String connString, Properties info) {
if (connString == null) {
throw ExceptionFactory.createException(WrongArgumentException.class, Messages.getString("ConnectionString.0"));
}
// 这里会将Properties中的信息拿出来进行拼接
String connStringCacheKey = buildConnectionStringCacheKey(connString, info);
ConnectionUrl connectionUrl;
// ........ 省略代码
return connectionUrl;
}

看下具体的代码:

    private static String buildConnectionStringCacheKey(String connString, Properties info) {
StringBuilder sbKey = new StringBuilder(connString);
sbKey.append("\u00A7"); // Section sign.
sbKey.append(
info == null ? null : info.stringPropertyNames().stream().map(k -> k + "=" + info.getProperty(k)).collect(Collectors.joining(", ", "{", "}")));
return sbKey.toString();
}

将k和value进行连接,最终拼接成:jdbc:mysql://127.0.0.1:3306/mysql_index_test§{user=root, password=root}

我们的properties中可以写哪些参数呢?

具体可以参考PropertyKey这个枚举类

存在问题

上述的手动加载Driver并且获取连接的过程稍显笨拙:如果现在我们加载进来了多个驱动Driver,那么手动创建Driver实例,并根据URL进行创建连接就会显得代码杂乱无章,并且还容易出错,并且不方便管理。JDBC中提供了一个DriverManager角色,用来管理这些驱动Driver。

这就是为什么要引入DriverManager的原因,要统一来进行管理不同厂商提供的Driver驱动!

DriverManager的功能

事实上,一般我们操作Driver,获取Connection对象都是交给DriverManager统一管理的。

DriverManger可以注册和删除加载的驱动程序,可以根据给定的url获取符合url协议的驱动Driver或者是建立Conenction连接,进行数据库交互。

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

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

在一个项目中可以使用到不同类型的数据库,那么就需要有对应的驱动来进行支持。Java为了能够满足对不同数据库类型的支持,也为了能够统一管理。

利用Java内置的SPI机制来进行加载这些驱动

答案就在于: SPI技术

SPI技术

SPI全称为 (Service Provider Interface):是JDK内置的一种服务提供发现机制。

SPI是一种动态替换发现的机制,一种解耦非常优秀的思想。

SPI工作原理: 就是ClassPath路径下的META-INF/services文件夹中, 以接口的全限定名来命名文件名,文件里面写该接口的实现。然后再资源加载的方式,读取文件的内容(接口实现的全限定名), 然后再去加载类。

spi可以很灵活的让接口和实现分离, 让api提供者只提供接口, 第三方来实现。

所以我们可以在MySQL依赖中找到META-INF/services/java.sql.Driver,然后文件中的内容是:

com.mysql.cj.jdbc.Driver

参考连接:

https://huaweicloud.csdn.net/63874ededacf622b8df8a9b9.html?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2defaultCTRLISTactivity-1-123450610-blog-118364823.pc_relevant_multi_platform_whitelistv3&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2defaultCTRLISTactivity-1-123450610-blog-118364823.pc_relevant_multi_platform_whitelistv3&utm_relevant_index=1

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

在下面回来详细进行说明

使用DriverManager获取指定Driver

驱动加载如内存的过程章节中,演示了Class.forName("...Driver")的方式,将不同数据库厂商的驱动加载到DriverManager中的CopyOnWriteArrayList来进行保存。

对于驱动加载后,如何获取指定的驱动程序呢?这里,DriverManager的静态方法getDriver(String url)可以通过传递给的URL,返回可以打开此URL连接的Driver。

比如,我想获取oracle的数据库驱动,只需要传递形如jdbc:oracle:thin:@::或者jdbc:oracle:thin:@//:/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
// 不同驱动类的acceptsURL方法对URL来做校验,如果满足,说明当前存在对应的驱动
if (localDriverInfo.driver.acceptsURL(paramString)) {
//返回对应的driver
return localDriverInfo.driver;
}
} catch (SQLException localSQLException) {
}
else
println(" skipping: "+ localDriverInfo.driver.getClass().getName());
}
// 遍历完成所有的驱动之后,还没有找到,那么就抛出异常,说明没有对应的驱动支持对应的URL协议
throw new SQLException("No suitable driver", "08001");
//-----省略部分代码
}
为什么可以通过URL来获取得到Driver
    private static boolean isDriverAllowed(Driver var0, ClassLoader var1) {
boolean var2 = false;
if (var0 != null) {
Class var3 = null; try {
// 得到对应的类,然后加载进来!!这里是类,而不是对象
var3 = Class.forName(var0.getClass().getName(), true, var1);
} catch (Exception var5) {
var2 = false;
} var2 = var3 == var0.getClass();
} return var2;
}

因为DriverManger就是为了统一加载各种Driver的,不如利用多态机制让各自的类来进行实现。

因为对于Oracle和MySQL来说,都有各自的驱动,这里通过SPI机制来进行加载。

使用DriverManager注册和取消注册驱动Driver

在开始的地方讨论了当使用Class.forName("driverName")加载驱动的时候,会向DriverManager中注册一个Driver实例。以下代码将验证此说法:

	public static void defaultDriver(){
try { String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe"; //1.将Driver加载到内存中,然后执行其static静态代码,创建一个OracleDriver实例注册到DriverManager中
Class.forName("oracle.jdbc.driver.OracleDriver");
//取出对应的oracle 驱动Driver
Driver driver = DriverManager.getDriver(url);
System.out.println("加载类后,获取Driver对象:"+driver); //将driver从DriverManager中注销掉
DriverManager.deregisterDriver(driver);
//重新通过url从DriverManager中取Driver
driver = DriverManager.getDriver(url);
System.out.println(driver);
} catch (Exception e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} finally{ }
}

以上代码主要分以下几步:

  1. 首先是将 oracle.jdbc.driver.OracleDriver加载到内存中;
  2. 然后便调用DriverManager.getDriver()去取Driver实例;
  3. 将driver实例从DriverManager中注销掉;
  4. 尝试再取对应url的Driver实例

上述代码执行的结果如下:

从执行结果看,正好能够验证以上论述:当第四步再次获取对应url的 Driver 实例时,由于已经被注销掉了,找不到适当的驱动Driver,抛出了 "Not suitable driver" 的异常。

	public static void defaultDriver(){
try { String url = "jdbc:oracle:thin:@127.0.0.1:1521:xe"; //1.将Driver加载到内存中,然后执行其static静态代码,创建一个OracleDriver实例注册到DriverManager中
Driver dd = (Driver)Class.forName("oracle.jdbc.driver.OracleDriver").newInstance();
//2.取出对应的oracle 驱动Driver
Driver driver = DriverManager.getDriver(url);
System.out.println("加载类后,获取Driver对象:"+driver); //3. 将driver从DriverManager中注销掉
DriverManager.deregisterDriver(driver); //4.此时DriverManager中已经没有了驱动Driver实例,将创建的dd注册到DriverManager中
DriverManager.registerDriver(dd); //5.重新通过url从DriverManager中取Driver
driver = DriverManager.getDriver(url); System.out.println("注销掉静态创建的Driver后,重新注册的Driver: "+driver);
System.out.println("driver和dd是否是同一对象:" +(driver==dd));
} catch (Exception e) {
System.out.println("加载Oracle类失败!");
e.printStackTrace();
} finally{ }
}

以下代码运行的结果:

以上代码先创建了一个Driver对象,在注销了DriverManager中由加载驱动过程中静态创建驱动之后,注册到系统中,现在DriverManager中对应url返回的Driver 即是在代码中创建的Driver对象。

使用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);

DriverManager 初始化

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

    static {
// 加载并初始化所有的Driver
loadInitialDrivers();
println("JDBC DriverManager initialized");
SET_LOG_PERMISSION = new SQLPermission("setLog");
DEREGISTER_DRIVER_PERMISSION = new SQLPermission("deregisterDriver");
}

可以看下如何来进行初始化的:

    private static void loadInitialDrivers() {
String var0;
try {
// 利用SPI机制的首选
var0 = (String)AccessController.doPrivileged(new PrivilegedAction<String>() {
public String run() {
// 加载系统变量 jdbc.drivers 设置的冒号隔开的驱动
return System.getProperty("jdbc.drivers");
}
});
} catch (Exception var8) {
var0 = null;
} AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
// 点进去看下,是固定目录:META-INF/services/
// 加载固定的类到内存中来
ServiceLoader var1 = ServiceLoader.load(Driver.class);
Iterator var2 = var1.iterator();
try {
while(var2.hasNext()) {
var2.next();
}
} catch (Throwable var4) {
} return null;
}
});
// ........省略代码
}
证明

在上面的过程中,使用Class.forName来进行加载驱动并将Driver注册到DriverManager中的。

但是现在看完了DriverManager的静态方法之后,也可以不使用Class.forName来加载驱动。

证明jdbc.drvers来获取当前项目中的驱动,首先利用maven项目引入oracle和MySQL对应的坐标

        <dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.27</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.oracle.database.jdbc/ojdbc8 -->
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>21.1.0.0</version>
</dependency>

然后写一段代码:

    public static void main(String[] args) {
Enumeration<Driver> drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()){
Driver driver = drivers.nextElement();
String driverName = driver.getClass().getName();
System.out.println("获取得到驱动的名称--->"+driverName);
}
}

打印结果:

获取得到驱动的名称--->com.mysql.cj.jdbc.Driver
获取得到驱动的名称--->oracle.jdbc.OracleDriver

总结

1、JDBC针对不同的数据库厂商通过接口来约束对应的行为;比如说:校验URL是否符合厂商条件、连接时候对参数进行校验;

2、JDBC为了针对各种数据库厂商提供的驱动进行管理,引入了DriverManager类处理

3、JDBC利用SPI技术来加载管理维护不同数据库厂商的驱动;

重点理解上面的两个图即可:

JDBC之Driver和DriverMananger的更多相关文章

  1. Java JDBC Thin Driver 连接 Oracle 三种方法说明(转载)

    一.JDBC 连接Oracle 说明 JDBC 的应用连接Oracle 遇到问题,错误如下: ORA-12505,TNS:listener does not currently know of SID ...

  2. JDBC Thin Driver 的formats三种格式

    格式一:  Oracle JDBC Thin using a ServiceName: jdbc:oracle:thin:@//<host>:<port>/<servic ...

  3. jdbc mysql driver 6.0.2

    url = jdbc:mysql://localhost:3306/hibernate?useUnicode=true&characterEncoding=UTF-8&useLegac ...

  4. 解决"java.lang.ClassNotFoundException: com.mysql.jdbc.Driver"

    按照以前的老方法,写Java的主程序通过JDBC来连MySQL. //1: import java.sql.*; import java.sql.*; public class JDBC_Driver ...

  5. 解决Mybatis连接Sql server 出现 Cannot load JDBC driver class 'com.mysql.jdbc.Driver '的问题

    tomcat启动的时候没有错误,但是进行数据库操作就会有错误. 在网上找了很久  好不容易找到解决方法 转自 http://blog.csdn.net/ro_bot/article/details/5 ...

  6. ambari-server启动出现ERROR main] DBAccessorImpl:106 - Error while creating database accessor java.lang.ClassNotFoundException:com.mysql.jdbc.Driver问题解决办法(图文详解)

    不多说,直接上干货! 问题详情 ambari-server启动时,报如下的错误 问题分析 注:启动ambari访问前,请确保mysql驱动已经放置在/usr/share/Java内且名字是mysql- ...

  7. MYSQL 之 JDBC(一): 数据库连接(一)通过Driver接口获取数据库连接

    通过Driver接口获取数据库连接 数据持久化 数据库存取技术分类 JDBC直接访问数据库 JDO技术 第三方O/R工具,如Hibernate,ibatis等JDBC是java访问数据库的基石 JDB ...

  8. JDBC API Description

    package java.sql description What the JDBCTM 4.2 API Includes Versions What the java.sql Package Con ...

  9. JDBC ODBC区别

    一.JDBC(Java DataBase Connectivity standard) 1.JDBC,它是一个面向对象的应用程序接口(API), 通过它可访问各类关系数据库. 2. 驱动程序(JDBC ...

  10. 常见JDBC连接数据库字符串

    1.Mysql 驱动类:com.mysql.jdbc.Driver 连接字符串:jdbc:mysql://localhost:3306/dbname 2.Oracle 驱动类:oracle.jdbc. ...

随机推荐

  1. 挂上burpsuite代理之后显示505 HTTP Version Not Supported 解决方法

    505 HTTP Version Not Supported  什么意思呢? HTTP505状态码代表的意思是 服务器不支持的HTTP版本,即 HTTP 505 HTTP Version Not Su ...

  2. Swift async await 使用介绍

    // // ViewController.swift // AsynWait // // Created by shengjie on 2022/2/9. // import UIKit class ...

  3. Ansible 实记

    自动化运维工具 Ansible ansible是基于模块工作的,本身没有批量部署的能力.真正具有批量部署的是ansible所运行的模块,ansible只是提供一种框架.主要包括: (1).连接插件co ...

  4. 激光雷达ldlidar communication is abnormal.

    查看串口设置是否正常,可以通过cat /dev/ttyS4查看是否有数据以确定所接的串口是否正确

  5. python之shapely库的使用

    参考链接:  https://www.pudn.com/news/6228d5049ddf223e1ad1d411.html : https://desktop.arcgis.com/zh-cn/ar ...

  6. python接口测试常见问题。

    一.入参问题 1.body字段类型 1.如果数据是从excel提取的那么中文数据会提示错误. 解决方法# media_value['body'] = media_value['body'].encod ...

  7. HCIP-进阶实验03-网络流量路径控制

    HCIP-进阶实验03-网络流量路径控制 实验需求 某城域网网络环境部署规划如图所示,该网络通过OSPF协议进行部署设计,分为四个区域,分别为骨干区域0.普通区域1.2.3.其中普通区域1为特殊区域N ...

  8. docker rabbitMQ安装

    1.环境准备 服务器 CENTOS 7 版本 安装docker容器 2.开始安装 docker pull rabbitmq:management 说明:为什么不直接安装 docker pull rab ...

  9. git远程分支回退到某个版本

    1.找到要回退的版本号(右击项目--> Git --> Show History -->选中要回退的版本-->Copy Revision Number): 2.打开idea的T ...

  10. Request processing failed;

    用 ssm 框架修改数据库数据时,出现了 Request processing failed; nested exception is org.mybatis.spring.MyBatisSystem ...