spring声明事务管理
一、数据库连接池
在程序启动时建立足够的数据库连接放置在内存中(List),这些连接组成连接池由程序动态的对池中的连接进行申请,使用,释放。
优势:资源重用;由于数据库连接得以重用,避免了频繁创建,释放连接引起的大量性能开销;另一方面也增加了系统运行环境的平稳性。
更快的系统反应速度;数据库连接池在初始化过程中,往往已经创建了若干数据库连接置于连接池中备用。此时连接的初始化工作均已完成。对于业务请求处理而言,直接利用现有可用连接,从而减少了系统的响应时间。
统一的连接管理,避免数据库连接泄露; 在较为完善的数据库连接池实现中,可根据预先的占用超时设定,强制回收被占用连接,避免了常规数据库连接操作中可能出现的资源泄露。
常见的数据库连接池
C3P0 Proxool DBCP Druid
配置C3P0数据源
需要c3p0数据库连接池类库 c3p0-0.9.2.1.jar mchange-commons-java-0.2.3.4.jar
将C3P0数据源纳入IOC容器中
1 <context:property-placeholder location="jdbc.properties"/> 2 <!-- ComboPooledDataSource 实现了javax.sql.DataSource接口 --> 3 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> 4 5 <property name="driverClass" value="${jdbc.driverClass}"/> 6 <property name="jdbcUrl" value="${jdbc.url}"/> 7 <property name="user" value="${jdbc.user}"/> 8 <property name="password" value="${jdbc.password}"/> 9 10 <!-- 个性化配置 --> 11 <property name="initialPoolSize" value="3"/> 12 <property name="minPoolSize" value="3"/> 13 <property name="maxPoolSize" value="3"/> 14 15 <property name="maxIdleTime" value="21800"/> 16 <property name="maxConnectionAge" value="21800"/> 17 </bean>
数据库连接核心配置通常是在属性配置文件中,<context:property-placeholder/>会读取jdbc.properties信息到IOC容器中。
连接池数据源主要是应用于在配置hibernate的sessionFactory获取数据库连接
1 <!-- 引入hibernate的sessionFactory --> 2 <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean" destroy-method="destroy"> 3 <property name="dataSource" ref="dataSource"/> 4 5 <property name="hibernateProperties"> 6 <props> 7 <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> 8 <prop key="hibernate.show_sql">true</prop> 9 <prop key="hibernate.format_sql">true</prop> 10 <prop key="hibernate.hbm2ddl.auto">none</prop> 11 </props> 12 </property> 13 <property name="packagesToScan" value="proj.entity"/> 14 </bean>
在属性dataSource注入上面配置的c3p0数据源
二、Spring事务管理
事务管理器:
Spring事务管理功能核心是事务管理器,Spring为不同的数据访问框架提供了不同的事务管理器,从而支持各种数据访问框架的事务管理功能;
Spring为数据访问框架提供的事务管理器均实现Spring的策略接口PlatformTransactionManager,该接口定义如下方法: getTransaction()返回一个已经激活的事务或创建一个新的事务 commit()提交当前事务 rollback() 回滚当前事务
Spring内置的事务管理器有:
DataSourceTransactionManager 数据源事务管理器,用于对单个数据源进行事务管理,通常用于JDBC事务管理或者mybatis事务管理
JdoTransactionManager Jdo事务管理器,用于Spring整合jdo时对jdo事务进行管理
JpaTransactionManager JPA事务管理器,用于Spring整合JPA时对JPA进行数据管理
HibernateTransactionManager Hibernate事务管理器,用于Spring整合Hibernate时对进行事务管理。
将Hibernate事务管理器纳入IoC容器管理:
1 <!-- 定义hibernate事务管理器 --> 2 <bean id="txManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> 3 <!-- 注入sessionFactory --> 4 <property name="sessionFactory" ref="sessionFactory"/> 5 </bean>
配置事务管理器后,Spring并不能自动对事务进行管理,还需要开发人员进行事务策略管理和控制
声明式事务管理:通过在Spring配置文件中引入tx命名空间的形式,基于xml配置或者注解配置的事务管理形式,事务管理无须与侵入核心业务。
Spring声明式事务管理是基于AOP和线程绑定技术实现,利用AOP实现开启、关闭事务并且织入到指定业务中,利用线程绑定实现事务跨越多个方法的传播。
所以在ioc容器中已经无法获取dao层或者service层的接口实现对象,只能获取代理对象。
Spring事务:
Spring事务分为物理事务和逻辑事务:
物理事务就是底层数据库支持的事务,如JDBC提供事务
逻辑事务是Spring管理的事务,逻辑事务提供更丰富的控制,而且如果想得到Spring事务管理的好处,必须使用逻辑事务,因此在Spring中如果没特别强调一般就是逻辑事务 Spring声明式事务管理就是基于逻辑事务。
事务属性:
事务隔离级别:用来解决并发事务时出现的问题,Spring事务隔离级别主要有以下几种:
ISOLATION_DEFAULT:默认隔离级别,即使用底层数据库默认的隔离级别;
ISOLATION_READ_UNCOMMITTED:读未提交;
ISOLATION_READ_COMMITTED:提交读,一般情况下我们使用这个;
ISOLATION_REPEATABLE_READ:可重复读;
ISOLATION_SERIALIZABLE:序列化。
事务只读:将事务标识为只读,只读事务不修改任何数据。
对于JDBC只是简单的将连接设置为只读模式,对于更新将抛出异常;
而对于一些其他ORM框架有一些优化作用,如在Hibernate中,Hibernate会话在只读事务模式下不用尝试检测和同步持久对象的状态的更新,以提高程序效率。
事务传播行为: Spring管理的事务是逻辑事务,而且物理事务和逻辑事务最大差别就在于事务传播行为。
事务传播行为用于指定在多个事务方法间调用时,事务是如何在这些方法间传播的,Spring共支持7种传播行为。
事务传播行为: Required:必须有逻辑事务,否则新建一个事务,表示如果当前存在一个逻辑事务,则加入该逻辑事务,否则将新建一个逻辑事务。
RequiresNew:创建新的逻辑事务,表示每次都创建新的逻辑事务(物理事务也是不同的)
Supports:支持当前事务,指如果当前存在逻辑事务,就加入到该逻辑事务,如果当前没有逻辑事务,就以非事务方式执行
NotSupported:不支持事务,如果当前存在事务则暂停该事务,即以非事务方式执行
Mandatory:必须有事务,否则抛出异常
Never:不支持事务,如果当前存在是事务则抛出异常
Nested:嵌套事务支持,如果当前存在事务,则在嵌套事务内执行,如果当前不存在事务,则创建一个新的事务
基于xml的声明式事务管理:
1 <!-- 配置事务通知 --> 2 <tx:advice id="txAdvice" transaction-manager="txManager"> 3 <tx:attributes> 4 <!-- 为指定的方法配置事务策略 --> 5 <!-- propagation="REQUIRED" propagation用于指定事务的传播行为,增删改一般都是用REQUIRED,查询操作一般指定为SUPPORT --> 6 <!-- read-only="false"设置事务是否为只读的,适应于查询操作,提高查询效率 --> 7 <!-- rollback-for用于指定出现什么样的异常当前方法所处的事务进行回滚,默认是RuntimeException --> 8 <tx:method name="save*" propagation="REQUIRED" /> 9 <tx:method name="add*" propagation="REQUIRED" /> 10 <tx:method name="insert*" propagation="REQUIRED" /> 11 <tx:method name="update*" propagation="REQUIRED" /> 12 <tx:method name="modify*" propagation="REQUIRED" /> 13 <tx:method name="edit*" propagation="REQUIRED" /> 14 <tx:method name="delete*" propagation="REQUIRED" /> 15 <tx:method name="remove*" propagation="REQUIRED" /> 16 <tx:method name="get*" propagation="SUPPORTS" read-only="true" /> 17 <tx:method name="find*" propagation="SUPPORTS" read-only="true" /> 18 <tx:method name="count*" propagation="SUPPORTS" read-only="true" /> 19 <tx:method name="list*" propagation="SUPPORTS" read-only="true" /> 20 <tx:method name="*" propagation="SUPPORTS" read-only="true" /> 21 22 </tx:attributes> 23 24 </tx:advice>
通过<aop:advisor>指定事务切面 Spring声明式事务管理通过AOP代理方式实现事务管理,利用环绕通知TransactionInterceptor实现事务的开启及关闭,且为单通知切面
1 <!-- 定义切面 --> 2 <aop:config> 3 <aop:advisor advice-ref="txAdvice" pointcut="execution(* proj.service..*.*(..))"/> 4 </aop:config>
dataSource --->sessionFactory ----->dao ------>service