http://www.mldn.cn/articleview/2008-6-23/article_view_3195.htm
一、前言
本文的目的是將一個獲取數據庫連接的普通類重構成DAO+Abstract Factory模式。
二、設計初衷
使用數據訪問對象(DAO,Data Access Object)模式來抽象和封裝所有對數據源的訪問。DAO管理着與數據源的連接以便檢索和存儲數據。可以降低商業邏輯層和數據訪問層的耦合度,提高應用的可維護性和可移植性。
由於底層數據源實現變化時,DAO向客戶端提供的接口不會變化,所有該模式允許DAO調整到不同的存儲模式,而不會影響其客戶端或者業務組件。顯然,DAO充當了組件和數據源之間的適配器。
三、重構
首先,創建一個獲取數據庫連接的普通類:
DAOClient.java
import java.sql.*;
publicclass DAOClient {
publicstaticvoid main( String[] args ) {
try {
//For Oracle
Class.forName( "oracle.jdbc.driver.OracleDriver" );
Connection conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
System.out.println( conn.toString() );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
}
}
再將這段代碼封裝到一個getConnection()方法中以便其它的地方調用:
import java.sql.*;
publicclass DAOClient {
publicstaticvoid main( String[] args ) {
Connection conn = getConnection();
System.out.println( conn.toString() );
}
/**
*得到一個Connection對象
*@returnjava.sql.Connection
*/
privatestatic Connection getConnection() {
Connection conn = null;
try {
//For Oracle
Class.forName( "oracle.jdbc.driver.OracleDriver" );
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
return conn;
}
}
再將此方法定義到針對Oracle的工廠類中:
OracleDAOFactory.java
import java.sql.*;
publicclass OracleDAOFactory {
private OracleDAOFactory() {}
/**
*返回一個OracleDAOFactory對象
*@returnOracleDAOFactory類型對象
*/
publicstatic OracleDAOFactory newInstance() {
returnnew OracleDAOFactory();
}
/**
*得到一個Connection對象
*@returnjava.sql.Connection
*/
public Connection getConnection() {
Connection conn = null;
try {
//For Oracle
Class.forName( "oracle.jdbc.driver.OracleDriver" );
conn = DriverManager.getConnection(
"jdbc:oracle:thin:@localhost:1521:dy", "scott", "tiger" );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
return conn;
}
}
此時,DAOClient.java這個測試類的代碼應修改爲:
import java.sql.*;
public class DAOClient {
publicstaticvoid main( String[] args ) {
Connection conn = OracleDAOFactory.newInstance().getConnection();
System.out.println( conn.toString() );
}
}
考慮:通常,數據庫服務器、數據庫名、數據庫用戶、密碼等應該從配置文件中獲取。因此,修改Oracle的工廠類:
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
publicclass OracleDAOFactory {
privatestatic Properties prop = new Properties();
static {
try {
prop.load( OracleDAOFactory.class
.getResourceAsStream( "config.properties" ) );
} catch ( IOException e ) {
System.out.println( "File:config.properties no find,PLS check out!" );
e.printStackTrace();
}
}
private String CONNECTION_SERVER_NAME = prop
.getProperty( "oracle_server_name" );
private String CONNECTION_DRIVER = prop.getProperty( "oracle_conn_driver" );
private String CONNECTION_DBINSTANCE = prop
.getProperty( "oracle_dbInstance" );
private String CONNECTION_USER = prop.getProperty( "oracle_conn_user" );
private String CONNECTION_PWD = prop.getProperty( "oracle_conn_pwd" );
private String CONNECTION_URL = "jdbc:oracle:thin:@"
+ CONNECTION_SERVER_NAME + ":1521:" + CONNECTION_DBINSTANCE;
private OracleDAOFactory() {}
/**
*返回一個OracleDAOFactory對象
*@returnOracleDAOFactory類型對象
*/
publicstatic OracleDAOFactory newInstance() {
returnnew OracleDAOFactory();
}
/**
*得到一個Connection對象
*@returnjava.sql.Connection
*/
public Connection getConnection() {
Connection conn = null;
try {
Class.forName( CONNECTION_DRIVER );
conn = DriverManager.getConnection(
CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
return conn;
}
}
添加配置文件config.properties:
oracle_server_name=localhost
oracle_conn_driver=oracle.jdbc.driver.OracleDriver
oracle_dbInstance=dy
oracle_conn_user=scott
oracle_conn_pwd=tiger
繼續考慮,客戶端在獲取數據庫連接時使用的是針對Oracle的數據庫的工廠,但如果數據庫變化了,那麼客戶端的代碼還是要改變。因此,可以定義一個DAOFactory類,定義了一個抽象方法:getConnection()用於獲取數據庫連接,還有一個getDAOFactory()方法,根據參數dbType的值,返回不同的DAOFactory。
DAOFactory.java
import java.sql.Connection;
publicabstractclass DAOFactory {
publicstaticfinalintORACLE = 1;
publicstaticfinalintSQLSERVER = 2;
publicstaticfinalintMYSQL = 3;
public abstract Connection getConnection();
publicstatic DAOFactory getDAOFactory( int dbType ) {
switch( dbType ) {
caseORACLE:
return OracleDAOFactory.newInstance();
caseSQLSERVER:
return SqlDAOFactory.newInstance();
caseMYSQL:
return MySqlDAOFactory.newInstance();
default:
returnnull;
}
}
}
SqlDAOFactory.java
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
publicclass SqlDAOFactory extends DAOFactory {
privatestatic Properties prop = new Properties();
static {
try {
prop.load( OracleDAOFactory.class
.getResourceAsStream( "config.properties" ) );
} catch ( IOException e ) {
System.out.println( "File:config.properties no find,PLS check out!" );
e.printStackTrace();
}
}
private String CONNECTION_SERVER_NAME = prop
.getProperty( "sqlserver_server_name" );
private String CONNECTION_DRIVER = prop.getProperty( "sqlserver_conn_driver" );
private String CONNECTION_DBINSTANCE = prop
.getProperty( "sqlserver_dbInstance" );
private String CONNECTION_USER = prop.getProperty( "sqlserver_conn_user" );
private String CONNECTION_PWD = prop.getProperty( "sqlserver_conn_pwd" );
private String CONNECTION_URL = "jdbc:microsoft:sqlserver://"
+ CONNECTION_SERVER_NAME + ":1433;DatabaseName="
+ CONNECTION_DBINSTANCE;
private SqlDAOFactory() {}
/**
*返回一個SqlDAOFactory對象
*@returnSqlDAOFactory類型對象
*/
publicstatic SqlDAOFactory newInstance() {
returnnew SqlDAOFactory();
}
/**
*得到一個Connection對象
*@returnjava.sql.Connection
*/
public Connection getConnection() {
Connection conn = null;
try {
Class.forName( CONNECTION_DRIVER );
conn = DriverManager.getConnection(
CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
return conn;
}
}
MySqlDAPFactory.java
import java.io.IOException;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
publicclass MySqlDAOFactory extends DAOFactory {
privatestatic Properties prop = new Properties();
static {
try {
prop.load( OracleDAOFactory.class
.getResourceAsStream( "config.properties" ) );
} catch ( IOException e ) {
System.out.println( "File:config.properties no find,PLS check out!" );
e.printStackTrace();
}
}
private String CONNECTION_SERVER_NAME = prop
.getProperty( "mysql_server_name" );
private String CONNECTION_DRIVER = prop.getProperty( "mysql_conn_driver" );
private String CONNECTION_DBINSTANCE = prop
.getProperty( "mysql_dbInstance" );
private String CONNECTION_USER = prop.getProperty( "mysql_conn_user" );
private String CONNECTION_PWD = prop.getProperty( "mysql_conn_pwd" );
private String CONNECTION_URL = "jdbc:mysql://"
+ CONNECTION_SERVER_NAME + ":3306/" + CONNECTION_DBINSTANCE
+ "?useUnicode=true&characterEncoding=UTF-8";
private MySqlDAOFactory() {}
/**
*返回一個MySqlDAOFactory對象
*@returnMySqlDAOFactory類型對象
*/
publicstatic MySqlDAOFactory newInstance() {
returnnew MySqlDAOFactory();
}
/**
*得到一個Connection對象
*@returnjava.sql.Connection
*/
public Connection getConnection() {
Connection conn = null;
try {
Class.forName( CONNECTION_DRIVER );
conn = DriverManager.getConnection(
CONNECTION_URL, CONNECTION_USER, CONNECTION_PWD );
} catch ( ClassNotFoundException e ) {
e.printStackTrace();
} catch ( SQLException e ) {
e.printStackTrace();
}
return conn;
}
}
修改config.properties配置文件:
#Oracle
oracle_server_name=localhost
oracle_conn_driver=oracle.jdbc.driver.OracleDriver
oracle_dbInstance=dy
oracle_conn_user=scott
oracle_conn_pwd=tiger
#SqlServer
sqlserver_server_name=localhost
sqlserver_conn_driver=com.microsoft.jdbc.sqlserver.SQLServerDriver
sqlserver_dbInstance=test
sqlserver_conn_user=sa
sqlserver_conn_pwd=sa
#MySql
mysql_server_name=localhost
mysql_conn_driver=com.mysql.jdbc.Driver
mysql_dbInstance=test
mysql_conn_user=root
mysql_conn_pwd=root
最後,修改客戶端文件DAOClient.java代碼:
import java.sql.*;
public class DAOClient {
public static void main( String[] args ) {
DAOFactory dao = DAOFactory.getDAOFactory( DAOFactory.ORACLE );
Connection conn = dao.getConnection();
System.out.println( conn.toString() );
}
}
通過這種DAO+(Abstract)Factory方式,在將程序遷移到其它數據庫中時,在客戶端程序中幾乎不用做修改,唯一需要做的,就是在獲得DAOFactory對象的時候,修改相應的參數,例如,遷移到MySql下的時候:
DAOFactory dao = DAOFactory.getDAOFactory( DAOFactory.MYSQL );