環境:
Java SE 1.5
Spring-2.5.1
mysql-connector-java-5.1.5.zip
Mysql 5.x
為了從數據庫中取得數據,我們首先需要獲取一個數據庫連接。 Spring通過DataSource對象來完成這個工作。 DataSource是JDBC規范的一部分, 它被視為一個通用的數據庫連接工廠。通過使用DataSource, Container或Framework可以將連接池以及事務管理的細節從應用代碼中分離出來。 作為一個開發人員,在開發和測試產品的過程中,你可能需要知道連接數據庫的細節。 但在產品實施時,你不需要知道這些細節。通常數據庫管理員會幫你設置好數據源。
在使用Spring JDBC時,你既可以通過JNDI獲得數據源,也可以自行配置數據源( 使用Spring提供的DataSource實現類)。使用後者可以更方便的脫離Web容器來進行單元測試。 這裡我們將使用DriverManagerDataSource,不過DataSource有多種實現, 後面我們會講到。使用DriverManagerDataSource和你以前獲取一個JDBC連接 的做法沒什麼兩樣。你首先必須指定JDBC驅動程序的全限定名,這樣DriverManager 才能加載JDBC驅動類,接著你必須提供一個url(因JDBC驅動而異,為了保證設置正確請參考相關JDBC驅動的文檔), 最後你必須提供一個用戶連接數據庫的用戶名和密碼。
以上兩段文字摘自Spring開發文檔原文,下面我寫的一個小的應用,用來測試Srping JDBC支持的效果。
下面這個測試要實現一個目標:通過獲取Spring的數據源來查詢MySQL數據庫testdb的一個表t_user數據。
一、創建項目,加載程序用到的工具包和驅動。並在源代碼目錄中添加Spring的配置文件ApplicationContext.xml,配置內容如下:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--數據庫的數據源定義-->
<bean id="rptds" class="org.springframework.jdbc.datasource.DriverManagerDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/testdb</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>leizhimin</value>
</property>
</bean>
</beans>
二、然後創建數據庫環境:
create database if not exists testdb;
DROP TABLE IF EXISTS t_user;
CREATE TABLE t_user (
id int(11) NOT NULL auto_increment,
firstname varchar(50) default NULL,
lastname varchar(50) default NULL,
zipcode varchar(10) default NULL,
tel varchar(20) default NULL,
address varchar(200) default NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB DEFAULT CHARSET=gbk;
insert into t_user(id,firstname,lastname,zipcode,tel,address) values
(1,'haha','hehe','234444','13577788999','阿斯地方'),
(2,'lei','aaa','450000','13939012107','鄭州市經三路');
三、Spring Bean容器環境獲取工具類
package com.lavasoft.dbtest;
import org.springframework.context.support.ClassPathXmlApplicationContext;
/**
* Created by IntelliJ IDEA.
* File: ContextHelper.java
* User: leizhimin
* Date: 2008-2-21 14:20:46
* Spring Bean容器環境獲取工具類
*/
public final class ContextHelper {
private static ClassPathXmlApplicationContext _ctx;
static {
_ctx = new ClassPathXmlApplicationContext("ApplicationContext.xml");
}
private ContextHelper() {
}
public static ClassPathXmlApplicationContext getContext() {
return _ctx;
}
}
三、寫獲取數據庫工具類
package com.lavasoft.dbtest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.CallableStatement;
/**
* Created by IntelliJ IDEA.
* File: DBUtil.java
* User: leizhimin
* Date: 2008-2-21 14:26:30
* 數據庫工具
*/
public final class DBUtil {
private static final Log log = LogFactory.getLog(DBUtil.class);
/**
* 獲取系統的數據源
*
* @return DataSource
*/
public static DataSource getDataSource() {
DataSource dataSource = null;
try {
dataSource = (DataSource) ContextHelper.getContext().getBean("rptds");
} catch (Exception e) {
log.error("獲取數據源出錯,請檢查Spring數據源配置!");
}
return dataSource;
}
/**
* 獲取數據庫連接
*
* @return Connection
*/
public static Connection makeConnection() {
Connection conn = null;
try {
conn = getDataSource().getConnection();
} catch (SQLException e) {
log.error("通過數據源獲取數據庫連接發生異常!");
e.printStackTrace();
}
return conn;
}
/**
* 執行沒有參數的SQL過程
*
* @param procedureName 存儲過程名字
* @return boolean 返回存儲過程執行的結果,true表示執行成功,false表示執行失敗.
*/
public static boolean executeBSDProcedure(String procedureName) {
boolean flag = false;
String sqlStr = "{call " + procedureName + "()}";
CallableStatement cs;
Connection conn = makeConnection();
try {
cs = (CallableStatement) conn.prepareStatement(sqlStr);
cs.executeUpdate(sqlStr);
flag = true;
} catch (SQLException e) {
log.error("調用存儲過程" + sqlStr + "失敗!");
e.printStackTrace();
}
return flag;
}
}
四、寫測試類
package com.lavasoft.dbtest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.ResultSet;
import java.sql.SQLException;
/**
* Created by IntelliJ IDEA.
* File: Test.java
* User: leizhimin
* Date: 2008-2-21 14:41:49
* Spring 數據源應用測試
*/
public class Test {
private static final Log log = LogFactory.getLog(Test.class);
public static void main(String args[]) {
Test.test();
}
public static void test() {
String testSql = "select * from t_user";
Connection conn = DBUtil.makeConnection();
Statement stmt = null;
try {
stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT);
ResultSet rs = stmt.executeQuery(testSql);
while (rs.next()) {
String firstName = rs.getString("firstname");
String lastName = rs.getString("lastname");
System.out.println(firstName + " " + lastName);
}
} catch (SQLException e) {
e.printStackTrace();
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException e) {
log.info("關閉Statement對象出現異常!");
e.printStackTrace();
}
}
if (conn != null) {
try {
conn.close();
} catch (SQLException e) {
log.error("關閉數據庫連接失敗!");
e.printStackTrace();
}
}
}
}
}
測試運行結果:
haha hehe
lei aaa
Process finished with exit code 0
五、數據源置換
Spring實現的DriverManagerDataSource並沒有提供連接池的功能,只是用來作簡單的單機連接測試,並不適合使用於真正的項目當中,可以考慮用比較成熟的數據連接池來取代。Apache DBCP連接池是不錯,如要要替換,則需要加載DBCP相關的工具包。
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--數據庫的數據源定義-->
<bean id="rptds" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName">
<value>com.mysql.jdbc.Driver</value>
</property>
<property name="url">
<value>jdbc:mysql://localhost:3306/testdb</value>
</property>
<property name="username">
<value>root</value>
</property>
<property name="password">
<value>leizhimin</value>
</property>
</bean>
</beans>
現在所使用的是org.apache.commons.dbcp.BasicDataSource作為注入的DataSource實例,為了使用DBCP 的功能,您需要在Classpath路徑中設定commons-dbcp.jar、commons-pool.jar與commons- collections.jar。注意到在dataSource上設定了"destroy-method"屬性,如此可以確保BeanFactory在關閉時也一並關閉BasicDataSource。
六、使用JNDI數據源
如果您的Servlet容器提供了JNDI(Java Naming and Directory Interface)的DataSource,您也可以簡單的換上這個DataSource:
<?xml version="1.0" encoding="gb2312"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
<!--數據庫的數據源定義-->
<bean id="dataSource"
class="org.springframework.indi.JndiObjectFactoryBean">
<property name="jndiName">
<value>jdbc/testds</value>
</property>
</bean>
</beans>
為了使用org.springframework.indi.JndiObjectFactoryBean,您需要spring-context.jar,"jndiName"實際上要根據您所設定的JNDI查詢名稱。