随笔-86  评论-33  文章-0  trackbacks-0
DataSource注入

对于不同的数据库存取需求,我们使用JDBC来解决这个问题,对于不同的数据连接来源需求,Spring则提供了DataSource注入,更换数据来源只要在Bean定义文件中修改配置,而不用修改任何一行程序。

因应不同的系统,应用程序可能使用不同的数据来源,但如纯綷的使用 JDBC、透过连接池、或是透过JNDI等等,数据来源的更动是底层的行为,不应影响到上层的业务逻辑,为此,您可以在需要取得连接来源的Bean上保留一个数据来源注入的接口,让依赖的数据来源由该接口注入。例如我们来写一个简单的Bean:

DataBean.java

package  onlyfun.caterpillar; 
                                                                             
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定义档可以这么撰写:

<? xml version = " 1.0 "  encoding = " UTF-8 " ?>  

<! 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定义档就可以了:

<? xml version = " 1.0 "  encoding = " UTF-8 " ?>  

<! 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资料源,您也可以简单的换上这个数据源:

<? xml version = " 1.0 "  encoding = " UTF-8 " ?>  

<! 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查询名称

posted on 2006-11-07 09:03 Derek.Guo 阅读(5708) 评论(3)  编辑  收藏 所属分类: Java

评论:
# re: Spring DataSource注入 2007-10-23 15:14 | leefu
你好,我想问下,用JNDI的 DataSource,然后在java应用中用到DataBean,在DataBean中加上一个ExecuteQuery()方法,在频繁的调用这个ExecuteQuery()方法的时候会出现连接池用完 ORA-04031: 无法分配 2816 字节的共享内存,想问一下,用JNDI的 DataSource的时候该怎么解决这个连接池的问题,谢谢  回复  更多评论
  
# re: Spring DataSource注入[未登录] 2007-11-05 22:00 | Derek
@leefu
你好!
不管使用什么样的数据源datasource;都需要处理关闭数据库连接的问题!!连接池与非连接池不同的是在于,连接是被正真关闭还是被返回池中!!
通过JNDI的Datasource去获取的连接,同样需要你去CLOSE;否则池中的连接同样会被用完的;
那么关闭连接要么你纯手工完成,要么使用SPRING的TEMPLATE,让它帮你完成!  回复  更多评论
  
# re: Spring DataSource注入[未登录] 2008-11-28 15:51 | 啊啊
不错,不像其他文章搞的很乱  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 
MSN:envoydada@hotmail.com QQ:34935442