轉(zhuǎn)載:http://my.oschina.net/xiaomaoandhong/blog/60938
何為DataSource
DataSource 接口是 JDBC 2.0 API 中的新增內(nèi)容,它提供了連接到數(shù)據(jù)源的另一種方法。
作為 DriverManager 工具的替代項(xiàng),DataSource 對(duì)象是獲取連接的首選方法。
實(shí)現(xiàn) DataSource 接口的對(duì)象通常在基于JNDI API 的命名服務(wù)中注冊(cè)。
不管通過何種持久化技術(shù),都必須通過數(shù)據(jù)連接訪問數(shù)據(jù)庫(kù),在傳統(tǒng)的應(yīng)用中數(shù)據(jù)連接可以通過DriverManager獲的,
在Spring中,數(shù)據(jù)連接一般是通過數(shù)據(jù)源獲得的。在以往的應(yīng)用中,數(shù)據(jù)源一般是 Web應(yīng)用服務(wù)器提供的。
在Spring中,你不但可以通過JNDI獲取應(yīng)用服務(wù)器的數(shù)據(jù)源,也可以直接在Spring容器中配置數(shù)據(jù)源,
此外,你還可以 通過代碼的方式創(chuàng)建一個(gè)數(shù)據(jù)源,以便進(jìn)行無依賴的單元測(cè)試。
DataSource API定義:
|
import
java.sql.Connection; |
|
import
java.sql.SQLException; |
|
public
interface DataSource extends CommonDataSource,Wrapper {
|
|
Connection getConnection() throws
SQLException; |
|
Connection getConnection(String username, String password) |
在Spring中配置Datasource
1、JDBC
Spring本身也提供了一個(gè)簡(jiǎn)單的數(shù)據(jù)源實(shí)現(xiàn)類DriverManagerDataSource ,
它位于org.springframework.jdbc.datasource包中。這個(gè)類實(shí)現(xiàn)了javax.sql.DataSource接口,
但它并沒有提供池化連接的機(jī)制,每次調(diào)用getConnection()獲取新連接時(shí),只是簡(jiǎn)單地創(chuàng)建一個(gè)新的連接。
因此,這個(gè)數(shù)據(jù)源類比較適合在單元測(cè)試 或簡(jiǎn)單的獨(dú)立應(yīng)用中使用,因?yàn)樗恍枰~外的依賴類。
|
<!-- 配置Spring DriverManagerDatasource數(shù)據(jù)源從中獲取connection,引入數(shù)據(jù)庫(kù)驅(qū)動(dòng) --> |
|
class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > |
|
<property name= "locations" > |
|
<value>classpath:jdbc.properties</value> |
|
<bean id= "dataSource" destroy-method= "close" |
|
class = "org.springframework.jdbc.datasource.DriverManagerDataSource" > |
|
<property name= "driverClassName" value= "${jdbc.driverClassName}" />
|
|
<property name= "url" value= "${jdbc.url}" />
|
|
<property name= "username" value= "${jdbc.username}" />
|
|
<property name= "password" value= "${jdbc.password}" />
|
DriverManagerDataSource extends AbstractDriverBasedDataSource extends AbstractDataSource implements DataSource
DriverManagerDataSource.java
|
package
org.springframework.jdbc.datasource; |
|
import
java.sql.Connection; |
|
import
java.sql.DriverManager; |
|
import
java.sql.SQLException; |
|
import
java.util.Properties; |
|
import
org.springframework.util.Assert; |
|
import
org.springframework.util.ClassUtils; |
|
public
class DriverManagerDataSource extends AbstractDriverBasedDataSource {
|
|
public DriverManagerDataSource() {
|
|
public DriverManagerDataSource(String url) {
|
|
public DriverManagerDataSource(String url, String username, String password) { |
|
public DriverManagerDataSource(String url, Properties conProps) { |
|
setConnectionProperties(conProps); |
|
public DriverManagerDataSource(String driverClassName, String url, String username, String password) { |
|
setDriverClassName(driverClassName); |
|
public void
setDriverClassName(String driverClassName) { |
|
Assert.hasText(driverClassName, "Property 'driverClassName' must not be empty" ); |
|
String driverClassNameToUse = driverClassName.trim(); |
|
Class.forName(driverClassNameToUse, true , ClassUtils.getDefaultClassLoader()); |
|
catch (ClassNotFoundException ex) {
|
|
IllegalStateException ise = |
|
new IllegalStateException( "Could not load JDBC driver class [" + driverClassNameToUse
+ "]" ); |
|
if (logger.isInfoEnabled()) {
|
|
logger.info( "Loaded JDBC driver: " + driverClassNameToUse);
|
|
protected Connection getConnectionFromDriver(Properties props)
throws SQLException {
|
|
if (logger.isDebugEnabled()) {
|
|
logger.debug( "Creating new JDBC DriverManager Connection to [" + url +
"]" ); |
|
return getConnectionFromDriverManager(url, props);
|
|
protected Connection getConnectionFromDriverManager(String url, Properties props) throws
SQLException { |
|
return DriverManager.getConnection(url, props);
|
DriverManagerDataSource建立連接是只要有連接就新建一個(gè)connection,根本沒有連接池的作用。
Spring在第三方依賴包中包含了兩個(gè)數(shù)據(jù)源的實(shí)現(xiàn)類包,其一是Apache的DBCP,其二是 C3P0。
2、DBCP
DBCP類包位于 /lib/jakarta-commons/commons-dbcp.jar,DBCP是一個(gè)依賴 Jakarta commons-pool對(duì)象池機(jī)制的數(shù)據(jù)庫(kù)連接池,
所以在類路徑下還必須包括/lib/jakarta- commons/commons-pool.jar。
|
<!-- 配置Spring dbcp Datasource數(shù)據(jù)源從中獲取connection,引入commons-dbcp、commons-pool包,數(shù)據(jù)庫(kù)驅(qū)動(dòng) --> |
|
class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > |
|
<property name= "locations" > |
|
<value>classpath:jdbc.properties</value> |
|
<bean id= "dataSource" destroy-method= "close" |
|
class = "org.apache.commons.dbcp.BasicDataSource" > |
|
<property name= "driverClassName" value= "${jdbc.driverClassName}" />
|
|
<property name= "url" value= "${jdbc.url}" />
|
|
<property name= "username" value= "${jdbc.username}" />
|
|
<property name= "password" value= "${jdbc.password}" />
|
BasicDataSource.java
|
public
class BasicDataSource implements DataSource {
|
|
// Attempt to prevent deadlocks - see DBCP - 272 |
|
DriverManager.getDrivers(); |
BasicDataSource提供了close()方法關(guān)閉數(shù)據(jù)源,所以必須設(shè)定destroy-method=”close”屬性,
以便Spring容器關(guān)閉時(shí),數(shù)據(jù)源能夠正常關(guān)閉。除以上必須的數(shù)據(jù)源屬性外,還有一些常用的屬性:
defaultAutoCommit:設(shè)置從數(shù)據(jù)源中返回的連接是否采用自動(dòng)提交機(jī)制,默認(rèn)值為 true;
defaultReadOnly:設(shè)置數(shù)據(jù)源是否僅能執(zhí)行只讀操作, 默認(rèn)值為 false;
maxActive:最大連接數(shù)據(jù)庫(kù)連接數(shù),設(shè)置為0時(shí),表示沒有限制;
maxIdle:最大等待連接中的數(shù)量,設(shè)置為0時(shí),表示沒有限制;
maxWait:最大等待秒數(shù),單位為毫秒, 超過時(shí)間會(huì)報(bào)出錯(cuò)誤信息;
validationQuery:用于驗(yàn)證連接是否成功的查詢SQL語句,SQL語句必須至少要返回一行數(shù)據(jù);
removeAbandoned:是否自我中斷,默認(rèn)是 false ;
removeAbandonedTimeout:幾秒后數(shù)據(jù)連接會(huì)自動(dòng)斷開,在removeAbandoned為true,提供該值;
logAbandoned:是否記錄中斷事件, 默認(rèn)為 false;
3、C3P0
C3P0是一個(gè)開放源代碼的JDBC數(shù)據(jù)源實(shí)現(xiàn)項(xiàng)目,C3P0類包位于Spring中l(wèi)ib/c3p0/c3p0-0.9.1.2.jar。
|
<!-- 配置Spring ComboPooledDataSource數(shù)據(jù)源從中獲取connection,引入c3p0- 0.9 . 1.2 .jar,數(shù)據(jù)庫(kù)驅(qū)動(dòng) --> |
|
class = "org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" > |
|
<property name= "locations" > |
|
<value>classpath:jdbc.properties</value> |
|
<bean id= "dataSource" destroy-method= "close" |
|
class = "com.mchange.v2.c3p0.ComboPooledDataSource" > |
|
<property name= "driverClass" value= "${jdbc.driverClassName}" />
|
|
<property name= "jdbcUrl" value= "${jdbc.url}" />
|
|
<property name= "user" value= "${jdbc.username}" />
|
|
<property name= "password" value= "${jdbc.password}" />
|
通過查看ComboPooledDataSource的源碼我們發(fā)現(xiàn)此處的屬性設(shè)置和上面不同,分別為driverClass、jdbcUrl、user。
4、JNDI(Java Naming and Directory Interface)
如果應(yīng)用配置在高性能的應(yīng)用服務(wù)器(如WebLogic或Websphere等)上或Jboss、Tomcat等,我們可能更希望使用應(yīng)用服務(wù)器本身提供的數(shù)據(jù)源。
應(yīng)用服務(wù)器的數(shù)據(jù)源使用JNDI使用,Spring為此專門提供引用JNDI資源的org\springframework\jndi\JndiObjectFactoryBean類。
以tomcat6為例:
1、在tomcat目錄下conf\context.xml中的<Context>標(biāo)簽中加入
|
type= "javax.sql.DataSource" |
|
driverClassName= "com.mysql.jdbc.Driver" url= "jdbc: |
2、修改項(xiàng)目的web.xml文件加入
|
<res-ref-name>jndi</res-ref-name> |
|
<res-type>javax.sql.DataSource</res-type> |
|
<res-auth>Container</res-auth> |
3、在spring配置文件中配置Datasource
|
<!-- 從Tomcat配置的JNDI服務(wù)獲取數(shù)據(jù)源-->
|
|
class = "org.springframework.jndi.JndiObjectFactoryBean" > |
|
<property name= "jndiName" value= "java:comp/env/jndi" /> |
我們也可以采用下面的方式,但是要加入以下命名空間
xmlns:jee="http://www./schema/jee"
xsi:schemaLocation="http://www./schema/jee
http://www./schema/jee/spring-jee-2.5.xsd">
|
<!-- Spring 2.0 為獲取J2EE資源提供了一個(gè)jee命名空間,通過jee命名空間,可以有效地簡(jiǎn)化J2EE資源的引用。 --> |
|
<jee:jndi-lookup id= "dataSource" jndi-name= "java:comp/env/jndi" /> |
相關(guān)鏈接:http://hi.baidu.com/282518588/item/f8562799787c0338326eeb4f
|