Spring dataSource

1.何为dataSource

DataSource 接口是 JDBC 2.0 API 中的新增内容,它提供了连接到数据源的另一种方法。 
作为 DriverManager 工具的替代项,DataSource 对象是获取连接的首选方法。 
实现 DataSource 接口的对象通常在基于JNDI API 的命名服务中注册。

不管通过何种持久化技术,都必须通过数据连接访问数据库,在传统的应用中数据连接可以通过DriverManager获的, 
在Spring中,数据连接一般是通过数据源获得的。在以往的应用中,数据源一般是 Web应用服务器提供的。 
在Spring中,你不但可以通过JNDI获取应用服务器的数据源,也可以直接在Spring容器中配置数据源, 
此外,你还可以 通过代码的方式创建一个数据源,以便进行无依赖的单元测试。

DataSource API定义: 

 1 package javax.sql;
 2  
 3 import java.sql.Connection;
 4 import java.sql.SQLException;
 5 import java.sql.Wrapper;
 6  
 7 public interface DataSource  extends CommonDataSource,Wrapper {
 8  
 9   Connection getConnection() throws SQLException;
10    
11   Connection getConnection(String username, String password) 
12     throws SQLException;
13 }

2.在Spring中配置Datasource

Spring本身也提供了一个简单的数据源实现类DriverManagerDataSource , 
它位于org.springframework.jdbc.datasource包中。这个类实现了javax.sql.DataSource接口, 
但它并没有提供池化连接的机制,每次调用getConnection()获取新连接时,只是简单地创建一个新的连接。 
因此,这个数据源类比较适合在单元测试 或简单的独立应用中使用,因为它不需要额外的依赖类。

 1 <!-- 配置Spring DriverManagerDatasource数据源从中获取connection,引入数据库驱动 -->
 2     <bean
 3         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 4         <property name="locations">
 5             <value>classpath:jdbc.properties</value>
 6         </property>
 7     </bean>
 8  
 9     <bean id="dataSource" destroy-method="close"
10         class="org.springframework.jdbc.datasource.DriverManagerDataSource">
11         <property name="driverClassName" value="${jdbc.driverClassName}" />
12         <property name="url" value="${jdbc.url}" />
13         <property name="username" value="${jdbc.username}" />
14         <property name="password" value="${jdbc.password}" />
15     </bean
 1 package org.springframework.jdbc.datasource;
 2  
 3 import java.sql.Connection;
 4 import java.sql.DriverManager;
 5 import java.sql.SQLException;
 6 import java.util.Properties;
 7  
 8 import org.springframework.util.Assert;
 9 import org.springframework.util.ClassUtils;
10  
11  
12 public class DriverManagerDataSource extends AbstractDriverBasedDataSource {
13  
14     public DriverManagerDataSource() {
15     }
16  
17     public DriverManagerDataSource(String url) {
18         setUrl(url);
19     }
20  
21     public DriverManagerDataSource(String url, String username, String password) {
22         setUrl(url);
23         setUsername(username);
24         setPassword(password);
25     }
26  
27     public DriverManagerDataSource(String url, Properties conProps) {
28         setUrl(url);
29         setConnectionProperties(conProps);
30     }
31  
32     public DriverManagerDataSource(String driverClassName, String url, String username, String password) {
33         setDriverClassName(driverClassName);
34         setUrl(url);
35         setUsername(username);
36         setPassword(password);
37     }
38  
39     public void setDriverClassName(String driverClassName) {
40         Assert.hasText(driverClassName, "Property 'driverClassName' must not be empty");
41         String driverClassNameToUse = driverClassName.trim();
42         try {
43             Class.forName(driverClassNameToUse, true, ClassUtils.getDefaultClassLoader());
44         }
45         catch (ClassNotFoundException ex) {
46             IllegalStateException ise =
47                     new IllegalStateException("Could not load JDBC driver class [" + driverClassNameToUse + "]");
48             ise.initCause(ex);
49             throw ise;
50         }
51         if (logger.isInfoEnabled()) {
52             logger.info("Loaded JDBC driver: " + driverClassNameToUse);
53         }
54     }
55  
56     protected Connection getConnectionFromDriver(Properties props) throws SQLException {
57         String url = getUrl();
58         if (logger.isDebugEnabled()) {
59             logger.debug("Creating new JDBC DriverManager Connection to [" + url + "]");
60         }
61         return getConnectionFromDriverManager(url, props);
62     }
63  
64     protected Connection getConnectionFromDriverManager(String url, Properties props) throws SQLException {
65         return DriverManager.getConnection(url, props);
66     }
67  
68 }

DriverManagerDataSource建立连接是只要有连接就新建一个connection,根本没有连接池的作用。

Spring在第三方依赖包中包含了两个数据源的实现类

包,其一是Apache的DBCP,其二是 C3P0。 

2.1 Apache DBCP

在lib中引入commons-dbcp、commons-pool包
 1 <bean
 2         class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
 3         <property name="locations">
 4             <value>classpath:jdbc.properties</value>
 5         </property>
 6     </bean>
 7  
 8     <bean id="dataSource" destroy-method="close"
 9         class="org.apache.commons.dbcp.BasicDataSource">
10         <property name="driverClassName" value="${jdbc.driverClassName}" />
11         <property name="url" value="${jdbc.url}" />
12         <property name="username" value="${jdbc.username}" />
13         <property name="password" value="${jdbc.password}" />
14     </bean>
 1 public class BasicDataSource implements DataSource {
 2      
 3     static {
 4         // Attempt to prevent deadlocks - see DBCP - 272
 5         DriverManager.getDrivers();
 6     }
 7     .
 8     .
 9     .
10 }

BasicDataSource提供了close()方法关闭数据源,所以必须设定destroy-method=”close”属性, 
以便Spring容器关闭时,数据源能够正常关闭。除以上必须的数据源属性外,还有一些常用的属性: 
defaultAutoCommit:设置从数据源中返回的连接是否采用自动提交机制,默认值为 true; 
defaultReadOnly:设置数据源是否仅能执行只读操作, 默认值为 false; 
maxActive:最大连接数据库连接数,设置为0时,表示没有限制; 
maxIdle:最大等待连接中的数量,设置为0时,表示没有限制; 
maxWait:最大等待秒数,单位为毫秒, 超过时间会报出错误信息; 
validationQuery:用于验证连接是否成功的查询SQL语句,SQL语句必须至少要返回一行数据; 
removeAbandoned:是否自我中断,默认是 false ; 
removeAbandonedTimeout:几秒后数据连接会自动断开,在removeAbandoned为true,提供该值; 
logAbandoned:是否记录中断事件, 默认为 false; 

2.2 spring中的c3p0

引入c3p0-0.9.1.2.jar

 1     <bean id="dataSource"
 2         class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
 3         <property name="driverClass" value="${driverClassName}"></property>
 4         <property name="jdbcUrl" value="${url}"></property>
 5         <property name="user" value="${userName}"></property>
 6         <property name="password" value="${password}"></property>
 7         <property name="maxPoolSize" value="${jdbc.maxPoolSize}"/>
 8         <!-- 指定连接池中保留的最小连接数-->
 9         <property name="minPoolSize" value="${jdbc.minPoolSize}"/>
10         <!-- 指定连接池的初始化连接数  取值应在minPoolSize 与 maxPoolSize 之间.Default:3-->
11         <property name="initialPoolSize" value="${jdbc.initialPoolSize}"/>
12         <!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。 Default:0-->
13         <property name="maxIdleTime" value="${jdbc.maxIdleTime}"/>
14         <!-- 当连接池中的连接耗尽的时候c3p0一次同时获取的连接数. Default:3-->
15         <property name="acquireIncrement" value="${jdbc.acquireIncrement}"/>
16         <property name="maxStatements" value="${jdbc.maxStatements}"/>
17         <!-- 每60秒检查所有连接池中的空闲连接.Default:0 -->
18         <property name="idleConnectionTestPeriod" value="${jdbc.idleConnectionTestPeriod}"/>
19         <!--#从数据库获取新连接失败后重复尝试次数 默认 30-->
20         <property name="acquireRetryAttempts" value="${jdbc.acquireRetryAttempts}"/>
21         <property name="breakAfterAcquireFailure" value="${jdbc.breakAfterAcquireFailure}"/>
22     </bean>

destroy-method="close"的作用是当数据库连接不使用的时候,就把该连接重新放到数据池中,方便下次使用调用.

 1 #指定连接池的初始化连接数
 2 jdbc.initialPoolSize=10
 3 #指定连接池中保留的最大连接数
 4 jdbc.maxPoolSize=20
 5 #指定连接池中保留的最小连接数
 6 jdbc.minPoolSize=10
 7 #最大空闲时间,180秒内未使用则连接被丢弃。若为0则永不丢弃
 8 jdbc.maxIdleTime=1800
 9 #当连接池中的连接耗尽的时候c3p0一次同时获取的连接数
10 jdbc.acquireIncrement=3
11 #最多可以创建Statements对象的个数. . 就是可以执行SQL语句的对象的个数..
12 jdbc.maxStatements=100
13 #每60秒检查所有连接池中的空闲连接
14 jdbc.idleConnectionTestPeriod=60
15 #从数据库获取新连接失败后重复尝试次数 默认 30
16 jdbc.acquireRetryAttempts=30
17 #获取连接失败将会引起所有的等待连接池来获取连接的线程抛出异常,
18 #但是数据源乃有效保留,
19 #并在下次调用getConnection()的时候继续尝试获取连接
20 #如果为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭
21 #默认 false
22 jdbc.breakAfterAcquireFailure=true
 

2.3 JNDI(Java Naming and Directory Interface)

如果应用配置在高性能的应用服务器(如WebLogic或Websphere等)上或Jboss、Tomcat等,我们可能更希望使用应用服务器本身提供的数据源。 
应用服务器的数据源使用JNDI使用,Spring为此专门提供引用JNDI资源的orgspringframeworkjndiJndiObjectFactoryBean类。

以tomcat6为例: 
1、在tomcat目录下confcontext.xml中的<Context>标签中加入 

<Resource name="jndi"
        auth="Container"
        type="javax.sql.DataSource"
        password="mysql5"
        username="root"
        driverClassName="com.mysql.jdbc.Driver" url="jdbc:mysql://localhost:3306/spring"
        maxActive="5"
        maxIdle="2"
        maxWait="3000"
/>


2、修改项目的web.xml文件加入 
<resource-ref>
    <res-ref-name>jndi</res-ref-name>
    <res-type>javax.sql.DataSource</res-type>
    <res-auth>Container</res-auth>
</resource-ref>

3、在spring配置文件中配置Datasource 
<!-- 从Tomcat配置的JNDI服务获取数据源-->
    <bean id="dataSource"
        class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="java:comp/env/jndi"/>
    </bean>

天天学习,天天进步。。。。。。

原文地址:https://www.cnblogs.com/huzi007/p/4718199.html