-
java 手动加载数据库驱动_JAVA加载数据库驱动(JDBC)
2021-02-26 20:13:15JAVA加载数据库驱动(JDBC)前言之前,对Class.forName(...一、使用JDBC连接MySQL首先,来看一下正常使用Java操纵MySql的简单代码逻辑。public static boolean connectionMySqlDemo() {Connection conn = null...JAVA加载数据库驱动(JDBC)
前言
之前,对Class.forName("com.mysql.jdbc.Driver");这条动态加载JDBC驱动感觉很疑惑,故有了这篇短文。
一、使用JDBC连接MySQL
首先,来看一下正常使用Java操纵MySql的简单代码逻辑。
public static boolean connectionMySqlDemo() {
Connection conn = null;
try {
// 1、动态加载mysql驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、连接数据库
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?"
+ "user=root&password=1234&useUnicode=true&characterEncoding=UTF8");
// 3、声明一个Statement 用来执行sql语句
Statement stmt = conn.createStatement();
// 4、执行sql语句
stmt.executeUpdate("create table student(no_id char(20),name varchar(20),primary key(no_id))");
int result = stmt.executeUpdate("insert into student(no_id,name) values('1','fxleyu')");
if (result > 0) {
ResultSet rs = stmt.executeQuery("select * from student");
while (rs.next()) {
System.out.println(rs.getString(1));
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5、关闭数据库
if (conn != null) {
try {
conn.close();
return true;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return false;
}
在上述代码中,动态加载数据库驱动那条语句感觉独立于其余代码逻辑。感觉缺少其并无关系(当然缺少了会在链接数据库时报java.sql.SQLException: No suitable driver found for)。
二、疑惑
上述代码很容易理解,除了如下Class.forName("com.mysql.jdbc.Driver");。正常理解,该语句只是加载把com.mysql.jdbc.Driver加载到JVM中,没不会产生特殊作用。
阅读com.mysql.jdbc.Driver代码,可以发现其中的隐含逻辑。
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()
}
}
原来该类中有静态代码库,其加载到JVM时,会执行该静态代码库。而该代码块会把该类的对象实例自注册到DriverManager中。如此第一部分中的第二步就很容易理解了。
// 2、连接数据库
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?"
+ "user=root&password=1234&useUnicode=true&characterEncoding=UTF8");
其就是可以根据String来获得上述加载的驱动,从而可以正常访问数据库。
三、余以为
代码的逻辑很重要,而Class.forName("com.mysql.jdbc.Driver");单独来看只是一条孤立的语句。没有和上下文代码产生显示的关联,这就导致了余在前言中的疑惑。故,使用Class.forName("com.mysql.jdbc.Driver");来动态注册驱动,会对当前代码逻辑产生不利影响。
正常的逻辑,Class.forName方法就是加载一个指定类,并对该类做一些初始化工作(使用静态代码库),其不应该做一些其它逻辑,例如动态注册驱动。如果需要注册驱动时,应该让用户自己使用DriverManager.registerDriver(new com.mysql.jdbc.Driver());来显示注册。这样代码逻辑会很清晰。
但在这里使用显示注册并不合适。因为当new com.mysql.jdbc.Driver()的动作中,就有类的加载过程。在该过程中,已经把该驱动加载到了DriverManager的列表中。而有显示的注册了一次,故DriverManager的列表会有两个com.mysql.jdbc.Driver实例。也就是说,MySql的jdbc并不适合用来进行显示加载。
当然,也许使用Class.forName("com.mysql.jdbc.Driver");有MySql团队自己的考虑,而我当前视野并没有看到其好处。
四、结束
Talk is cheap, show me the code. 当对某些代码逻辑有疑问时,不妨查看一下相关源码,就会豁然开朗。自勉。P.S. 第三部分的余以为灵感借鉴于“余晟以为”微信公众号,很喜欢他那句“我是这么以为的,当然你也可以那么以为”。
参考
-
动态加载数据库驱动包
2018-08-16 23:27:21最近接到一个比较恶心的需求,里面有一个小功能,使用不同的数据库驱动动态连接数据库,搞了一个测试demo,废话少说直接上代码 package com.aotain.taskmgr; import java.net.URL; import java.net....最近接到一个比较恶心的需求,里面有一个小功能,使用不同的数据库驱动动态连接数据库,搞了一个测试demo,废话少说直接上代码
package com.aotain.taskmgr;
import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.DriverPropertyInfo;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLFeatureNotSupportedException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Logger;public class MycatMulitJdbcVersionTest {
private static final String JDBC_URL = "jdbc:mysql://localhost:3306/testdb?serverTimezone=UTC&useSSL=false"; private static final String USER = "root"; private static final String PASSWORD = "mysql"; private static final Map<String, String> jdbcVersionMap = new HashMap<String, String>(); private static final Map<String, Driver> tmpDriverMap = new HashMap<String, Driver>(); // 动态加载jdbc驱动 private static void dynamicLoadJdbc(String mysqlJdbcFile) throws Exception { URL u = new URL("jar:file:lib/" + mysqlJdbcFile + "!/"); String classname = jdbcVersionMap.get(mysqlJdbcFile); URLClassLoader ucl = new URLClassLoader(new URL[] { u }); Driver d = (Driver)Class.forName(classname, true, ucl).newInstance(); DriverShim driver = new DriverShim(d); DriverManager.registerDriver(driver); tmpDriverMap.put(mysqlJdbcFile, driver); } // 每一次测试完卸载对应版本的jdbc驱动 private static void dynamicUnLoadJdbc(String mysqlJdbcFile) throws SQLException { DriverManager.deregisterDriver(tmpDriverMap.get(mysqlJdbcFile)); } // 进行一次测试 private static void testOneVersion(String mysqlJdbcFile) { System.out.println("start test mysql jdbc version : " + mysqlJdbcFile); try { dynamicLoadJdbc(mysqlJdbcFile); } catch (Exception e1) { e1.printStackTrace(); } Connection conn = null; try { conn = DriverManager.getConnection(JDBC_URL, USER, PASSWORD); Statement stmt = conn.createStatement(); ResultSet rs = stmt.executeQuery("select user()"); System.out.println("select user() output : "); while(rs.next()) { System.out.println(rs.getObject(1)); } rs = stmt.executeQuery("show tables"); System.out.println("show tables output : "); while(rs.next()) { System.out.println(rs.getObject(1)); } } catch (SQLException e) { e.printStackTrace(); } finally { if(conn != null) { try { conn.close(); } catch (SQLException e) { e.printStackTrace(); } } } try { dynamicUnLoadJdbc(mysqlJdbcFile); } catch (SQLException e) { e.printStackTrace(); } System.out.println("end !!!"); System.out.println(); } public static void main(String[] args) { jdbcVersionMap.put("mysql-connector-java-6.0.3.jar", "com.mysql.cj.jdbc.Driver"); jdbcVersionMap.put("mysql-connector-java-5.1.6.jar", "com.mysql.jdbc.Driver"); jdbcVersionMap.put("mysql-connector-java-5.1.31.jar", "com.mysql.jdbc.Driver"); jdbcVersionMap.put("mysql-connector-java-5.1.35.jar", "com.mysql.jdbc.Driver"); jdbcVersionMap.put("mysql-connector-java-5.1.39.jar", "com.mysql.jdbc.Driver"); for(String mysqlJdbcFile : jdbcVersionMap.keySet()) { testOneVersion(mysqlJdbcFile); } }
}
class DriverShim implements Driver {
private Driver driver;
DriverShim(Driver d) { this.driver = d; }
public boolean acceptsURL(String u) throws SQLException {
return this.driver.acceptsURL(u);
}
public Connection connect(String u, Properties p) throws SQLException {
return this.driver.connect(u, p);
}
@Override
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
return this.driver.getPropertyInfo(url, info);
}
@Override
public int getMajorVersion() {
return this.driver.getMajorVersion();
}
@Override
public int getMinorVersion() {
return this.driver.getMinorVersion();
}
@Override
public boolean jdbcCompliant() {
return this.driver.jdbcCompliant();
}
@Override
public Logger getParentLogger() throws SQLFeatureNotSupportedException {
return this.driver.getParentLogger();
}
}- 我还是我,不一样的烟火*
-
java加载mysql驱动_Java 加载数据库驱动(JDBC)
2021-01-27 01:38:28这条动态加载JDBC驱动感觉很疑惑,故有了这...一、使用JDBC连接MySQL首先,来看一下正常使用Java操纵MySql的简单代码逻辑。1234567891011121314151617181920212223242526272829303132333435363738public static boo...前言
之前,对Class.forName("com.mysql.jdbc.Driver");这条动态加载JDBC驱动感觉很疑惑,故有了这篇短文。
一、使用JDBC连接MySQL
首先,来看一下正常使用Java操纵MySql的简单代码逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38public static boolean connectionMySqlDemo() {
Connection conn = null;
try {
// 1、动态加载mysql驱动
Class.forName("com.mysql.jdbc.Driver");
// 2、连接数据库
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?"
+ "user=root&password=1234&useUnicode=true&characterEncoding=UTF8");
// 3、声明一个Statement 用来执行sql语句
Statement stmt = conn.createStatement();
// 4、执行sql语句
stmt.executeUpdate("create table student(no_id char(20),name varchar(20),primary key(no_id))");
int result = stmt.executeUpdate("insert into student(no_id,name) values('1','fxleyu')");
if (result > 0) {
ResultSet rs = stmt.executeQuery("select * from student");
while (rs.next()) {
System.out.println(rs.getString(1));
}
}
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (SQLException e) {
e.printStackTrace();
} finally {
// 5、关闭数据库
if (conn != null) {
try {
conn.close();
return true;
} catch (SQLException e) {
e.printStackTrace();
}
}
}
return false;
}
在上述代码中,动态加载数据库驱动那条语句感觉独立于其余代码逻辑。感觉缺少其并无关系(当然缺少了会在链接数据库时报java.sql.SQLException: No suitable driver found for)。
二、疑惑
上述代码很容易理解,除了如下Class.forName("com.mysql.jdbc.Driver");。
正常理解,该语句只是加载把com.mysql.jdbc.Driver加载到JVM中,没不会产生特殊作用。
阅读com.mysql.jdbc.Driver代码,可以发现其中的隐含逻辑。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23public 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()
}
}
原来该类中有静态代码库,其加载到JVM时,会执行该静态代码库。
而该代码块会把该类的对象实例自注册到DriverManager中。
如此第一部分中的第二步就很容易理解了。
1
2
3// 2、连接数据库
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/test?"
+ "user=root&password=1234&useUnicode=true&characterEncoding=UTF8");
其就是可以根据String来获得上述加载的驱动,从而可以正常访问数据库。
三、余以为
代码的逻辑很重要,而Class.forName("com.mysql.jdbc.Driver");单独来看只是一条孤立的语句。
没有和上下文代码产生显示的关联,这就导致了余在前言中的疑惑。
故,使用Class.forName("com.mysql.jdbc.Driver");来动态注册驱动,会对当前代码逻辑产生不利影响。
正常的逻辑,Class.forName方法就是加载一个指定类,并对该类做一些初始化工作(使用静态代码库),
其不应该做一些其它逻辑,例如动态注册驱动。
如果需要注册驱动时,应该让用户自己使用DriverManager.registerDriver(new com.mysql.jdbc.Driver());来显示注册。
这样代码逻辑会很清晰。
但在这里使用显示注册并不合适。因为当new com.mysql.jdbc.Driver()的动作中,就有类的加载过程。在该过程中,已经把该驱动加载到了DriverManager的列表中。而有显示的注册了一次,故DriverManager的列表会有两个com.mysql.jdbc.Driver实例。也就是说,MySql的jdbc并不适合用来进行显示加载。
当然,也许使用Class.forName("com.mysql.jdbc.Driver");有MySql团队自己的考虑,而我当前视野并没有看到其好处。
四、结束
Talk is cheap, show me the code. 当对某些代码逻辑有疑问时,不妨查看一下相关源码,就会豁然开朗。自勉。P.S. 第三部分的余以为灵感借鉴于“余晟以为”微信公众号,很喜欢他那句“我是这么以为的,当然你也可以那么以为”。
参考
1、使用源码下载路径 http://101.96.8.142/dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz
-
jfinal mysql 配置_jfinal如何动态加载数据库配置
2021-02-01 06:39:28展开全部独立使用ActiveRecordActiveRecordPlugin可以独立于java web 环境运行在任何普通的java程序中,使62616964757a686964616fe78988e69d8331333365653837用方式极度简单,相对于web项目只需要手动调用一下其...展开全部
独立使用ActiveRecord
ActiveRecordPlugin可以独立于java web 环境运行在任何普通的java程序中,使62616964757a686964616fe78988e69d8331333365653837用方式极度简单,相对于web项目只需要手动调用一下其start() 方法即可立即使用。以下是代码示例:public class ActiveRecordTest {
public static void main(String[] args) {
DruidPlugin dp = new DruidPlugin("localhost", "userName", "password");
ActiveRecordPlugin arp = new ActiveRecordPlugin(dp);
arp.addMapping("blog", Blog.class);
// 与 jfinal web 环境唯一的不同是要手动调用一次相关插件的start()方法
dp.start();
arp.start();
// 通过上面简单的几行代码,即可立即开始使用
new Blog().set("title", "title").set("content", "cxt text").save();
Blog.dao.findById(123);
}
}
注意:ActiveRecordPlugin所依赖的其它插件也必须手动调用一下start()方法,如上例中的dp.start()。网页链接
把上面代码写在Controller中, 动态请求, 进行管理即可: 参考代码:网页链接
-
JAVA类的静态加载和动态加载以及NoClassDefFoundError和ClassNotFoundException
2012-06-06 11:53:20我们都知道JAVA初始化一个类的...我们把前者叫做JAVA的静态加载,把后者叫做动态加载.后者在很多框架中经常使用,通过用property文件的方式指定类名称.如我们熟悉的在写JDBC代码的时候加载不同数据库的驱动. 静态加载的时 -
动态加载JDBC Jar包连接数据库
2016-07-19 15:43:59在用Jmeter的时候,需要构造一些请求数据,所以为了方便大家使用,使用了动态加载jdbc jar包来连接数据库,以下是部分代码片段。 import java.io.*; import java.net.URL; import java.net.URLClassLoader; ... -
什么是Java的动态加载
2018-07-20 09:11:19在JAVA中,通过Class.forName()方法可以动态决定加载哪一个类,这个功能对于相同接口的不同实现来讲非常有用。比如对于设计好的数据库连接池接口,我们可以有多种的接口实现类来完成相同的功能,同时用户可以简单的... -
JAVA动态加载JAR包的实现
2013-07-08 14:30:00如何动态的加载这些驱动!不可能把所有的数据库驱动都集成到JAR包中吧?... 动态加载JAR包,使用JAR包里的类,代码如下: package org; import java.io.File; import java.net.URL; import java.net.UR... -
JAVA动态加载JAR包的实现,代码很简单,但对新手很难!
2012-04-12 18:18:29近来想做一个SWING界面的数据库管理软件,就是类似于PLSQL的软件(PLSQL非常完美,可惜只支持ORACLE)。由于要兼容的数据库类型众多,但还好,所有这些数据库类型都提供了对JDBC的支持,所以,这...于是动态加载驱动的 -
extjs tree java_Extjs 的Tree动态加载
2021-02-26 11:17:17经过几天的努力,终于搞定了,动态连接数据库加载tree莱单中Node,这个也在网上查了不少资料,可惜啊,基本上都是转载一人之手。看上去很麻烦。咋一看就头晕,功夫不负有心人,我终于找到一个算是简单的方法,但是,... -
java动态加载类
2014-04-25 14:46:00/*在JAVA中,通过Class.forName()方法可以动态决定加载哪一个类,这个功能对于相同接口的不同实现来讲非常有用。比如对于设计好的数据库连接池接口,我们可以有多种的接口实现类来完成相同的功能,同时用户可以简单... -
java创建动态数据源_spring框架中多数据源创建加载并且实现动态切换的配置实例代码...
2021-02-28 19:03:09在我们的项目中遇到这样一个问题:我们的项目需要连接多个数据库, 而且不同的客户在每次访问中根据需要会去访问不同的数据库。我们以往在spring和hibernate框架中总是配置一个数据源,因而 sessionFactory的... -
java 静态类 加载_java – 静态和动态类加载?
2021-03-06 04:36:51What is the need and advantage of this. Typically which is ...例如,在JDBC情况下,它允许您在不同的驱动程序实现之间切换,并且(理论上)不同的数据库供应商之间切换而不更改源代码.另一个用例是当某个供应商开发... -
关于java动态网页的创建和简单项目制作的问题,以及如何连接mysql数据库
2019-09-27 18:23:05** 网页配置和创建执行** 第一步要安装eclipse,并下载eclipse的web,java ee的插件。 第二步下载tomcat并安装 第三步,通过eclipse界面上方工具栏中的windows...第四步,编写简单java动态网页代码,将下方sever中的... -
通过JAVA按钮事件更新数据库内数据,同时动态的刷新窗口内显示的数据
2019-06-25 22:40:17//静态代码块(将加载驱动、连接数据库放入静态块中) static{ try { //1.加载驱动程序 Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"); //2.获得数据库的连接 conn=... -
04.26 day05 类加载器 类的加载流程 数据库连接池 设计模式
2019-04-26 17:37:241.java开发工具可以帮助我们将Java代码编译为class字节码 2.类加载器加载class字节码,将字节码里面的指令放到内存执行,并且将数据动态分配到jvm的内存模型中 3.jvm分区 类的加载流程 1、类的加载指的就是将class... -
一种B/S模式下基于JAVA反射机制的可伸缩动态加载模块的解决方案
2014-04-03 16:18:24项目主体采用B/S架构,在逻辑层需要用到不同形式的数据(分别可能从数据库或者配置文件进行读取所需数据),进而进行数据的业务计算,得出结果。 实际项目中,模型的设计是不同的部门或者单位进行设计,但是主运行... -
基于Java的DBLP数据库爬虫系统
2017-05-30 19:38:57Java爬虫系统,对DBLP(http://dblp.uni-trier.de/)中的论文信息进行爬取,爬取信息包括论文题目、作者、论文发表的会议名称、页码、年份、开会地点、开会日期等信息...实现了动态页面的加载(通过Chrome DevTools对网 -
Java代码实例
2016-06-21 22:44:5110.6 Java程序的加载过程 190 10.7 小结 192 第三篇 高级基础篇 第11章 异常处理——Java世界的医生 195 11.1 异常处理的基本知识 195 11.1.1 try和catch捕获异常 195 11.1.2 异常的传播过程 198 ... -
Java爬虫,爬取新闻网的标题、时间和图片,并存入MySQL数据库
2019-01-16 15:29:29实现爬取“淮师新闻网”的新闻列表、新闻详情信息,并将爬取到的信息存入数据库。 可以抓取非HTML信息(HttpClient):例如网页上动态加载的Json...Java代码,数据库信息,要导入的jar包,全都在 链接:https... -
基于mysql的gateway动态路由_Spring Cloud Gateway之动态路由(数据库版)
2021-02-07 22:18:291、实现动态路由的关键是RouteDefinitionRepository接口,该接口存在一个默认实现(InMemoryRouteDefinitionRepository)通过名字我们应该也知道该实现是将配置文件中配置的信息加载到内存中。因此无法实现动态路由。2... -
java从数据库读取两个字段存储到map中
2018-10-24 15:42:39之前自己一直接触的仅仅需要从数据库读取一个字段到java中,因此只需要定义一个动态数组ArrayList,将ResultSet中的结果存储到该动态数组中即可。而现在需要从数据库读入两个字段,在此简要描述一下如何从数据库读取... -
spring动态加载数据源+动态添加数据源
2016-11-24 09:07:17动态加载数据源关键一点:在系统运行时加载多一个数据源,加载此数据源的对象必须和系统启动时加载数据源的同一个,在我这里加载数据源的对象是类DynamicDataSource,可在这里添加一个加载数据源的方法: ... -
Java 项目生成静态页面的代码
2021-01-20 14:21:50不外乎有以下因素: 1、从... 3、从安全性来看:静态网页不宜遭到黑客攻击,因为黑客不知道你的网站的后台、网站采用程序、数据库的地址。 4、从稳定性来看:哪天数据库服务器挂了,动态网页就拜拜了!而要运行一个静 -
JAVAJava动态执行类的静态方法
2011-04-02 07:14:28forName()方法可以静态决议加载哪一个类, 比如关于设计好的数据库连接池接口, 我们可以有多种的接口完成类来完成相反的功能, 在源代码外面通过读取配置文件信息, forName(configClassName). 这样关于顺序来讲...