Spring DAO(1):基础 & 数据源配置

来源:互联网 发布:百度读书软件 编辑:程序博客网 时间:2024/05/20 07:53
DAO(Data Access Object)用于访问数据的对象,DAO 屏蔽了数据储存的最终介质和具体的实现技术细节;
Spring 提供了一套完善的DAO体系,用于屏蔽各种持久化技术的实现细节,以统一的管理方式进行管理;

统一的DAO异常体系

Spring 提供了一套和实现技术无关的、面向 DAO 层语义的异常体系,并通过转换器将不同的持久化技术的异常转换为Spring 的异常;

Spring DAO异常体系

Spring 以分类的方式建立了异常分类目录,对于大部分应用来说,该异常分类目录对于异常类型的划分具有适当的颗粒度;

异常转换器

对于不同持久化技术的异常转换为 Spring DAO异常,Spring 提供以下的异常转化器:
持久化技术异常转化器JDBCorg.springframework.jdbc.support.SQLExceptionTranslatorHibernateorg.springframework.orm.hibernateX.SessionFactoryUtilsMyBatis使用JDBC的异常转化器JPAorg.springframework.orm.jpa.EntiryManagerFactoryUtilsJDOorg.springframework.orm.jdo.PersistenceManagerFactoryUtils
※ Spring 4.0 对于 Hibernate 只支持 Hibernate 3.6 之后的版本;


数据访问模板支持

Spring DAO 为不同持久化技术提供了统一的模板,分别提供不同的模板类给予支持;
持久化技术模板类支持类JDBCorg.springframework.jdbc.core.JdbcTemplateorg.springframework.jdbc.core.JdbcSupportHibernateorg.springframework.orm.hibernateX.HibernateTemplateorg.springframework.orm.hibernateX.HibernateDaoSupportMyBatis直接使用 JDBC 的模板类和支持类JPAorg.springframework.orm.jpa.JpaTemplateorg.springframework.orm.jpa.JpaDaoSupportJDOorg.springframework.orm.jdo.JdoTemplateorg.springframework.orm.jdo.JdoDaoSupport


数据源配置

对于任何持久化技术,都需要数据连接,Spring 中数据连接时以通过数据源获取的;
Spring 主要使用的数据源有3种:
  • Apache DBCP 数据源
  • C3P0 数据源
  • JNDI 数据源

DBCP 数据源

DBCP 是一个依赖 Jakarta commons-pool 对象池机制的数据库连接池,所以在类路径下需要包含 commons-pool 类包;
使用 DBCP 数据源需要 commons-dbcp:commons-dbc 依赖包(已经包含 commons-pool 类包);
以下是使用 DBCP 配置 MySQL 数据源的片段:
 
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destory-method="close"
      p:dirverClassName="com.mysql.jdbc.Driver"
      p:url="jdbc:mysql://127.0.0.1:3306/sampleDB"
      p:username="root"
      p:password="1234"/>

以上配置的属性为必要属性,其中 destory-method 为配置数据源相应的关闭方法,以下是一些常用的配置属性:
分类属性默认值说明事务属性defaultAutoCommittrue连接池创建的连接默认 auto-commit 状态;defaultReadOnly驱动默认连接池创建的连接默认 read-only 状态;defaultTransactionIsolation驱动默认连接池创建的连接默认 transactionIsolation 状态;
可选值: NONE, READ_COMMITTED, READ_UNCOMMITTED, REPEATABLE_READ, SERIALIZABLE数据连接属性initialSize0初始化连接:连接池启动格式创建的初始化连接数量;maxActive8最大活动连接:连接池中允许的保持活动状态的最大连接池数量,超过的活动连接将被释放,设置为负数值则不限制;maxIdle / minIdle8 / 0最大/最小 空闲连接;maxWait-1(无限)最大等待时间:当没有可用连接时,连接池等待连接被归还的最大时间(毫秒单位),超过时间则抛出异常;缓存设置poolPreparedStatementsfalse开始连接池的 prepared statement 功能,所有 CallableStatement 和 PreparedStatement 都会被缓存起来maxOpenPreparedStatments0(无限制) PreparedStatement 池能够同时分配的打开的 statements 的最大数量;连接泄露回收removeAbandonedfalse标记是否删除可能存在泄露的连接,该条件在 (getNumIdle() <2) and (getNumActive() > getMaxActive() -3) 满足时触发;removeAbandonedTimeout300泄露的连接可以被回收的超时值(单位秒)连接维护和检测validationQuery指定一个 SQL SELECT 语句,在将连接返回给调用者之前,使用该 SQL 语句验证从连接池中取出的连接是否可用;testOnBorrowtrue是否从连接池中取出来连接前进行检验,如果检验失败,则从连接池中取出该连接并尝试取出另一个连接;testOnReturnfalse是否在归还到链接池中前进行检验;testWhileIdlefalse连接是否被空闲连接回收期进行检验,如果验证失败,则从连接池中去除;timeBetweenEvicitionRunsMills-1空闲连接线程的运行周期(单位毫秒),设置为负数不运行空闲连接回收线程;numTestsPerEvicitionRun3在每次空闲连接回收器线程运行时检查的连接数量;minEvictabledIdleTimeMills100 *60*30连接在连接池存空闲时间达到该值时,空闲回收器将其进行回收(单位毫秒)

C3P0 数据源

C3P0 是一个开源的 JDBC 数据源实现项目,实现了 JDBC3 和 JDBC2 拓展规范说明的 Connection 和 Statement 池;
使用 DBCP 数据源需要 com.mchange:c3p0 依赖包;
以下是使用 DBCP 配置 MySQL 数据源的片段:
 
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destory-method="close"
      p:dirverClass="com.mysql.jdbc.Driver"
      p:jdbcUrl="jdbc:mysql://127.0.0.1:3306/sampleDB"
      p:username="root"
      p:password="1234"/>
C3P0 除了包含以上 CBCP 拥有的配置属性外,还包含以下更多常用的配置:
属性默认值说明acquireIncrement3当连接池中的连接用完时,C3P0 一次性创建新连接的数目;acquireRetryAttempts30从数据库获取新连接失败后重复尝试获取的次数;acquireRetryDelay1000参数获取连接的间隔时间(单位毫秒);autoCommitOnClosefalse连接关闭时默认将所有未提交的操作回滚;propertyCycle300用户修改系统配置参数执行前的最多等待参数(单位秒)breakAfterAquireFailurefalse声明为false,获取连接失败将会引起所有等待获取连接的线程抛出异常,大概数据源仍有效保留,并在下次调用 getConnection() 时继续尝试获取连接;声明为 true 时数据源将断开并永久关闭;checkoutTimeout0(无限)当连接池用完时,客户端调用 getConnection() 方法后等待获取新连接的时间,超出后抛出 SQLException (单位毫秒)idleConnectionTestPeriod0(不检查)间隔多少秒检查所有连接池的空闲连接(单位秒);initialPoolSize3初始化时创建的连接数;minPoolSize / maxPoolSize0 / 15连接池中保留的最小 / 最大连接数量;maxIdleTime0(不限制)连接的最大空闲时间(单位毫秒);maxStatements0JDBC 的标准参数,用于控制数据源内加载 PreparedStatement 数量,maxStatementsPerConnection0连接池内单个连接所拥有的最大缓存 Statements数,当maxStatements 和 maxStatementsPerConnection 同时设置为 0 时,缓存关闭;numHelperThreads3C3P0 是异步操作的,缓慢的 JDBC 通过帮助进程完成,拓展这些操作可以有效提高性能;

JNDI 数据源

如果应用配置在高性能的应用服务器(WebLogic、WebSphere等)上,则可能更希望使用应用服务器本身提供的数据源(当该数据源使用 JNDI 开放时),Spring 提供了引用 JNDI 数据源的 JndiObjectFactoryBean 类;
以下是一个引用 JNDI 源的片段:
 
<bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean"
      p:jndiName="java:comp/env/jdbc/bbt" />
<!-- jndiName 指向引用的 JNDI 数据源-->
Spring 为获取 Java EE 资源提供了一个 jee 命名空间,通过 jee 空间命名,可以有效地简化 Java EE 资源的引用,以下片段示例使用 jee 命名空间引用 JNDI 数据源的位置:
 
<beans ...>
    <jee:jndi-lookup id="dataSorce" jndi-name="java:comp/env/jdbc/bbt" />
</beans>


使用属性文件配置数据源

以上配置 DBCP 和 C3P0 数据源时,是将数据源连接参数硬编码到bean配置文件中,在实际项目中,为了维护连接数据的安全性和方便修改,往往会将这些连接数据存放到一个配置文件中,然后通过 SpEL 调用该配置文件的参数到bean配置文件;
将 C3P0 数据源的连接参数存放到 jdbc.properties 
 
jdbc.driverClass=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql//127.0.0.1:3306/sampleDB
jdbc.userName=root
jdbc.password=1234
配置数据源bean片段
 
<context:property-placeholder location="classpath:jdbc.properties" />
<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destory-method="close"
      p:dirverClass="#{jdbc.driverClass}"
      p:jdbcUrl="#{jdbc.url}"
      p:username="#{userName}"
      p:password="#{passowrd}" />


解决MySQL的“8小时问题”

如果使用数据库为MySQL,当数据源配置不当时,很容易发生经典的 ”8小时问题“,原因是 MySQL 默认情况如果发现一个连接的空闲时间超过8个小时,则会在数据库端自动关闭该连接,而数据源不知道该数据源连接已经被数据库关闭了,当这个无用的连接返回给某个 DAO 时,DAO 会报无法获取 Connection 的异常;

在采用 DBCP 或 C3P0 的默认配置下,由于 testOnBorrow 属性的默认值为 true,即数据源在将连接交给 DAO 前,都会先检查该连接是否完好,所以并不会发生 ”8 小时问题“;但是这种默认的配置由于每次提交连接给DAO时都会检测连接的有效性,在高并发的应用中会带来性能问题;

一个推荐的高效解决方式如下:
设置 testOnBorrow 为 false,testWhileIdle 为 true,根据实际情况设置 timeBetweenEvictionRunsMills 的值;
这时,DBCP 和 C3P0 将会通过一个后台线程定时对空闲连接进行检测,当发现无用空闲连接时,就会将他们清除掉,只要 timeBetweenEvictionRunsMills 小于8小时,就可以避免 MySQL 的 ”8小时问题“;



 


原创粉丝点击