以下是一段使用jdbc连接MySql的代码:
public static void main(String[] args) {
Connection conn = null;
Statement state = null;
ResultSet set = null;
try {
// 注册数据库驱动
DriverManager.registerDriver(new Driver());
// 获取数据库连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "");
// 获取传输器对象
state = conn.createStatement();
// 利用传输器对象执行sql语句
set = state.executeQuery("select * from emp");
while (set.next()) {
System.out.println(set.getString("name"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
conn = null;
}
try {
set.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
set = null;
}
try {
state.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
state = null;
}
}
}
这段代码的通用性不够,如果换了一种数据库,比如这个月使用mysql的,发现mysql满足不了我们的程序要换一种数据库sql server,那是不是又要重新写一次这段代码呢?
以MySql为例:为了增加这段代码的通用性,在导包的时候要注意在给这些类导包的时候要导其接口包,不要导其实现类的包:
Connection:导java.sql.Connection;不导com.mysql.jdbc.Connection;
Statement:导import java.sql.Statement;不导com.mysql.jdbc.Statement;
那么经过这么改造,这段代码几乎是通用的了,现在需要更改数据库只需改以下两行代码就可以了:
// 注册数据库驱动
DriverManager.registerDriver(new Driver());
// 获取数据库连接
conn = DriverManager.getConnection("jdbc:mysql://localhost:3306/mydb", "root", "");
把第一行的参数更改成对应数据库的Driver对象,第二行更改成对应数据库的url,用户名,密码。
对于挑剔的人类来说这样还不够,第二行中的url,用户密码可以保存在一个配置类里面,然后把那三个参数改成配置类里面的对象,而第一行无论如何都是要更改的了,有什么办法可以使得换一种新数据库的时候一行代码都不用更改就可以使用呢?
方法还是有的我们看一下MySql驱动jar包的Driver类的源代码:
//
// Register ourselves with the DriverManager
//
static {
try {
java.sql.DriverManager.registerDriver(new Driver());
} catch (SQLException E) {
throw new RuntimeException("Can't register driver!");
}
}
可以看到在静态代码块里也执行了一次注册操作,那么上面第一段代码中的:
// 注册数据库驱动
DriverManager.registerDriver(new Driver());
也就是说在注册new Driver()的时候已经注册过一次了,然后实例化Driver之后再注册一次,换句话说就是注册了两次。
虽然在使用上影响不大,但是终归不好,有没有方法可以不重复注册地调用注册呢?而且这段源码跟代码的通用性有啥关系呢?
我们都知道静态代码块在类加载的时候就会执行,我们接下来就利用这种特性给我们的代码改造!
只需使用Class.forName();去加载Driver就可以使驱动jar包注册。下面请看修改过的代码:
package com.javy.jdbc;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class JdbcDemo1 {
private final static String DRIVERNAME="com.mysql.jdbc.Driver";
private final static String DATABASEURL="jdbc:mysql://localhost:3306/mydb";
private final static String DATABASE_USERNAME="root";
private final static String DATABASE_PWD="";
public static void main(String[] args) {
Connection conn = null;
Statement state = null;
ResultSet set = null;
try {
// 注册数据库驱动
Class.forName(DRIVERNAME);
// 获取数据库连接
conn = DriverManager.getConnection(DATABASEURL,DATABASE_USERNAME , DATABASE_PWD);
// 获取传输器对象
state = (Statement) conn.createStatement();
// 利用传输器对象执行sql语句
set = state.executeQuery("select * from emp");
state.executeUpdate("");
while (set.next()) {
System.out.println(set.getString("name"));
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
try {
conn.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
conn = null;
}
try {
set.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
set = null;
}
try {
state.close();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
state = null;
}
}
}
}
可以看到如果需要换一种数据库的话我们只需要更改头部四个常量就可以了。