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. 第三部分的余以为灵感借鉴于“余晟以为”微信公众号,很喜欢他那句“我是这么以为的,当然你也可以那么以为”。
参考
1、使用源码下载路径 http://101.96.8.142/dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-5.1.40.tar.gz
网友评论