對于不同的數據庫存取需求,我們使用JDBC來解決這個問題,對于不同的數據連接來源需求,Spring則提供了DataSource注入,更換數據來源只要在Bean定義文件中修改配置,而不用修改任何一行程序。
因應不同的系統,應用程序可能使用不同的數據來源,但如純綷的使用 JDBC、透過連接池、或是透過JNDI等等,數據來源的更動是底層的行為,不應影響到上層的業務邏輯,為此,您可以在需要取得連接來源的Bean上保留一個數據來源注入的接口,讓依賴的數據來源由該接口注入。例如我們來寫一個簡單的Bean:
DataBean.java
import javax.sql.DataSource;
import java.sql.Connection;
public class DataBean {
private DataSource dataSource;
public void setDataSource(DataSource dataSource) {
this .dataSource = dataSource;
}
public void testDataSource() {
try {
Connection connection = dataSource.getConnection();
if (connection != null )
System.out.println( " test ok! " );
}
catch (Exception e) {
e.printStackTrace();
}
}
}
這是一個簡單的測試Spring DataSource注入的程序,我們透過javax.sql.DataSource接口來注入數據來源,Spring提供了 org.springframework.jdbc.datasource.DriverManagerDataSource來取得 DataSource,它實作了javax.sql.DataSource,您將之當作一個Bean,之后再注入DataBean中即可,Bean定義檔可以這么撰寫:
<! DOCTYPE beans PUBLIC " -//SPRING/DTD BEAN/EN " " http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " dataSource " class = " org.springframework.jdbc.datasource.DriverManagerDataSource " >
< 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 > caterpillar </ value >
</ property >
< property name = " password " >
< value > 123456 </ value >
</ property >
</ bean >
< bean id = " dataBean " class = " onlyfun.caterpillar.DataBean " >
< property name = " dataSource " >
< ref bean = " dataSource " />
</ property >
</ bean >
</ beans >
如果您之前只使用spring-core.jar這個類別庫,您還必須加入 spring-dao.jar, org.springframework.jdbc.datasource.DriverManagerDataSource是包括在這個類別庫中,如果您使用的是spring.jar,當中已經包括了,無需加入任何的jar,當然,為了使用JDBC,您必須要有JDBC驅動程序的jar檔。
可以用下面這段程序簡單的測試一下:
BeanDefinitionRegistry reg = new DefaultListableBeanFactory();
XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(reg);
reader.loadBeanDefinitions(new ClassPathResource("bean.xml"));;
BeanFactory bf = (BeanFactory) reg;
DataBean dataBean = (DataBean) bf.getBean("dataBean");
dataBean.testDataSource();
DriverManagerDataSource并沒有提供連接池的功能,只能作作簡單的單機連接測試,現在假設連接測試沒有問題了,您想要換上DBCP以獲得連接池的功能,則原程序不用更動,只要改改Bean定義檔就可以了:
<! DOCTYPE beans PUBLIC " -//SPRING/DTD BEAN/EN " " http://www.springframework.org/dtd/spring-beans.dtd " >
< beans >
< bean id = " dataSource " 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 > caterpillar </ value >
</ property >
< property name = " password " >
< value > 123456 </ value >
</ property >
</ bean >
< bean id = " dataBean " class = " onlyfun.caterpillar.DataBean " >
< property name = " dataSource " >
< ref bean = " dataSource " />
</ property >
</ bean >
</ beans >
現在我們使用的是org.apache.commons.dbcp.BasicDataSource作為注入的 DataSource源,為了使用DBCP的功能,您必須要將commons-dbcp.jar加入CLASSPATH中,另外您還需要commons- pool.jar與commons-collections.jar,這些都可以在Spring的相依版本中的lib目錄下找到。
注意到我們在dataSource Bean上宣告了destroy-method,如此可以確保BeanFactory在關閉時也一并關閉BasicDataSource。
如果您要直接使用JDBC來進行數據存儲,使用org.springframework.jdbc.datasource.DataSourceUtils來取得Connection會是更好的方式:
Connection conn = DataSourceUtils.getConnection(dataSource);
這樣作的好處是,所有的SQLException都被Spring的DataAccessException子類CannotGetJdbcConnectionException包裝起來。您可以獲得更多的信息,并保證存儲層的可移值性。
關閉Connection時,可以用下面的方式:
DataSourceUtils.closeConnectionIfNecessry(connection, dataSource);
如果您的Servlet容器提供了JNDI資料源,您也可以簡單的換上這個數據源:
<! 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 / TestDB </ value >
</ property >
</ bean >
< bean id = " dataBean " class = " onlyfun.caterpillar.DataBean " >
< property name = " dataSource " >
< ref bean = " dataSource " />
</ property >
</ bean >
</ beans >
為了使用org.springframework.indi.JndiObjectFactoryBean,您必須加入 spring-context.jar這個類別庫,jndiName實際上要根據您所設定的JNDI查詢名稱