以下是一段使用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;
}
}
}
}
可以看到如果需要換一種數據庫的話我們只需要更改頭部四個常量就可以了。