Sping事务管理

来源:互联网 发布:日本历史书籍推荐知乎 编辑:程序博客网 时间:2024/06/06 01:13

   

事务: 

逻辑上的一组操作,要么全发生,要么全不发生。

事务特性:

 一.原子性   二.一致性   三.隔离性   四.持久性

Sping事务管理:  

 编程式事务管理和声明式事务管理

编程式事务管理: 

Sping提供 DataSourceTransactionManager和 TransactionTemplate事务管理器模版类完成业务逻辑事务管理操作,可以直接在.xml配置:

核心配置:


<!-- 启用@AsjectJ支持 --><aop:aspectj-autoproxy />   <bean id="accountService" class="com.spring.transaction.demo1.AccountServiceImpl">    <property name="accountDao" ref="accountDao"></property>     </bean>       <bean id="accountDao" class="com.spring.transaction.demo1.AccountDaoImpl">     <!-- 将模版注入到AccountDaoImpl -->     <property name="jdbcTemplate" ref="jdbcTemplate"></property>      </bean>    <!--  传统方法配置数据源 -->   <bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource">          <property name="driverClassName" value="com.mysql.jdbc.Driver" />         <!--  注意一下&characterEncoding要修改为&characterEncoding   -->    <property name="url" value="jdbc:mysql://localhost:3306/pager"/>                <property name="username" value="root"/>          <property name="password" value="666123" />      </bean>        <!--配置jdbcTemplate(以创建一个jdbc模版,当然也可以继承JdbcDaoSupport获得模版) -->    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">    <!-- 将连接池注入到JdbcTemplate(获得连接) -->        <property name="dataSource" ref="dataSource"></property>    </bean>         <!--配置事务管理器 -->    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">    <!-- 将连接池注入到transactionManager -->        <property name="dataSource" ref="dataSource"></property>    </bean>         <!--配置事务管理器模版:Spring为简化事务管理的代码而提供的类 -->    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">    <!-- 将事务管理器注入模版-->        <property name="transactionManager" ref="transactionManager"></property>    </bean>     



声明式事务管理:只需要为Spring添加配置(XML/Annotation开启注解),就可以为目标代码(service)添加事务管理功能.

Spring事务管理高层抽象主要由PlatformTransactionManager/TransactionDefinition/TransactionStatus三个接口提供支持



事务描述DataSourceTransactionManagerJDBCTemplate/MyBatis/iBatis持久化使用HibernateTransactionManagerHibernate持久化使用JpaTransactionManagerJPA持久化使用JdoTransactionManagerJDO持久化使用JtaTransactionManagerJTA实现管理事务,一个事务跨越多个资源时使用

因此使用Spring管理事务,需要为不同持久层配置不同事务管理器实现.



TransactionDefinition(事务定义信息):

TransactionDefinition提供了对事务的相关配置, 如事务隔离级别/传播行为/只读/超时等:

  • 隔离级别(isolation) 
    为解决事务并发引起的问题(脏读/幻读/不可重复读),引入四个隔离级别:
隔离级别描述DEFAULT使用数据库默认的隔离级别READ_UNCOMMITED读未提交READ_COMMITTED读已提交(Oracle默认)REPEATABLE_READ可重复读(MySQL默认)SERIALIZABLE串行化

关于事务隔离级别的讨论, 可参考我的博客JDBC基础-事务隔离级别部分.


传播行为(propagation) :

传播行为不是数据库的特性, 而是为了在业务层解决两个事务相互调用的问题:

传播类型描述REQUIRED支持当前事务,如果不存在就新建一个(默认)SUPPORTS支持当前事务,如果不存在就不使用事务MANDATORY支持当前事务,如果不存在则抛出异常REQUIRES_NEW如果有事务存在,则挂起当前事务新建一个NOT_SUPPORTED以非事务方式运行,如果有事务存在则挂起当前事务NEVER以非事务方式运行,如果有事务存在则抛出异常NESTED如果当前事务存在,则嵌套事务执行(只对DataSourceTransactionManager有效)
  • 超时时间(timeout)
  • 只读(read-only) 
    只读事务, 不能执行INSERT/UPDATE/DELETE操作.


TransactionStatus(事务状态信息):


获得事务执行过程中某一个时间点状态.



声明式事务管理的实现:

1.传统方法,基于TransactionProxyFactoryBean的方式

2.基于AspectJ的XML配置的实现方式

3.基于注解的实现方式

1.基于TransactionProxyFactoryBean的方式:


核心配置:

<!-- 启用@AsjectJ支持 --><aop:aspectj-autoproxy />   <bean id="accountService" class="com.spring.transaction.demo2.AccountServiceImpl">    <property name="accountDao" ref="accountDao"></property>     </bean>       <bean id="accountDao" class="com.spring.transaction.demo2.AccountDaoImpl">     <!-- 将模版注入到AccountDaoImpl,这时jdbcTemplate已被Spring增强-->     <property name="jdbcTemplate" ref="jdbcTemplate"></property>      </bean>    <!--  传统方法配置数据源 -->   <bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource">          <property name="driverClassName" value="com.mysql.jdbc.Driver" />         <!--  注意一下&characterEncoding要修改为&characterEncoding   -->    <property name="url" value="jdbc:mysql://localhost:3306/pager"/>                <property name="username" value="root"/>          <property name="password" value="666123" />      </bean>        <!--配置jdbcTemplate(以创建一个jdbc模版,当然也可以继承JdbcDaoSupport获得模版) -->    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">    <!-- 将连接池注入到JdbcTemplate(获得连接) -->        <property name="dataSource" ref="dataSource"></property>    </bean>          <!--配置事务管理器 -->    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"></property>    </bean>         <!--配置业务层的代理 -->    <bean id="serviceProxyFactoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">    <property name="proxyInterfaces">     <!-- 至少一个接口(创建的代理对象和目标对象都要实现这些接口) -->      <list>       <value>com.spring.transaction.demo2.AccountService</value>      </list>     </property>      <!-- 配置目标对象-->     <property name="target" ref="accountService"></property>    <!-- 注入事务管理器-->        <property name="transactionManager" ref="transactionManager"></property>        <!-- 注入事务属性-->        <property name="transactionAttributes" >        <props>        <!--ISOLATION_:        readyOnly:        -Exception:        +Exception: -->        <prop key="transfer">PROPAGATION_REQUIRED</prop>        </props>        </property>    </bean> 

注意:

注入accountService时,name=“serviceProxyFactoryBean”,因为accountService Bean在serviceProxyFactoryBean中已被增强。

即,


@Resource(name="serviceProxyFactoryBean")
private AccountService accountService;


2.基于AspectJ的XML配置的实现方式:


核心思想:

AOP面向切面编程

在<aop:advisor>中引入在标签中配置 好的事务管理器<tx:advice>通知
<-- 启用@AsjectJ支持 --><aop:aspectj-autoproxy />   <bean id="accountService" class="com.spring.transaction.demo3.AccountServiceImpl">    <property name="accountDao" ref="accountDao"></property>     </bean>       <bean id="accountDao" class="com.spring.transaction.demo3.AccountDaoImpl">     <!-- 将模版注入到AccountDaoImpl,这时jdbcTemplate已被Spring增强-->     <property name="jdbcTemplate" ref="jdbcTemplate"></property>      </bean>    <!--  传统方法配置数据源 -->   <bean id="dataSource"  class="org.apache.commons.dbcp.BasicDataSource">          <property name="driverClassName" value="com.mysql.jdbc.Driver" />         <!--  注意一下&characterEncoding要修改为&characterEncoding   -->    <property name="url" value="jdbc:mysql://localhost:3306/pager"/>                <property name="username" value="root"/>          <property name="password" value="666123" />      </bean>        <!--配置jdbcTemplate(以创建一个jdbc模版,当然也可以继承JdbcDaoSupport获得模版) -->    <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">    <!-- 将连接池注入到JdbcTemplate(获得连接) -->        <property name="dataSource" ref="dataSource"></property>    </bean>          <!--配置事务管理器 -->    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"></property>    </bean>         <!--配置事务的通知 -->    <tx:advice id="txAdvice" transaction-manager="transactionManager">    <!-- 定义方法的过滤规则 -->    <tx:attributes>        <tx:method name="transfer"  propagation="REQUIRED" read-only="false"/>    </tx:attributes> </tx:advice>        <aop:config>     <aop:pointcut expression="execution(* com.spring.transaction.demo3+.*(..))" id="pointcut1"/>     <!-- 配置切面 -->     <aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>    </aop:config>

注意:

注入accountService时,name=“accountService”,因为accountService 在 Bean生成时,已经成为了一个代理类(自动代理)

3.基于注解的实现方式(简单):

 

 <!--配置事务管理器 -->    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">        <property name="dataSource" ref="dataSource"></property>    </bean>     <!-- 开启注解事务 -->    <tx:annotation-driven transaction-manager="transactionManager"/>

注意:

还需要在需要事务代理类上加上


@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT)



剩下的就交给Sping去做了!!!微笑微笑

 




0 0
原创粉丝点击