Spring事务管理——慕课网

来源:互联网 发布:星际公民 知乎 编辑:程序博客网 时间:2024/05/18 00:40

边看边写的代码:

http://download.csdn.net/detail/fulq1234/9755202

**2-1. 事务回顾**

  事务:逻辑上的一组操作,要么全部成功,要么全部失败。
  事务特性:
  原子性,一致性,隔离线,持久性
**3-1. 接口介绍**
  .Spring事务管理高层抽象主要包括3个接口:
  . PlatformTranctionManager 事务管理器
  . TransactionDefinition 事务定义信息(隔离,传播,超时,只读)
  . TransactionStatus 事务具体运行状态
**3-2. PlatformTransactionManager接口介绍**
  Spring为不同的持久化框架提供了不同PlatfromTransactionManager接口实现
  org.springframework.jdbc.datasource.DataSourceTransactionManager:使用Spring JDBC或iBatis进行持久化数据时使用
  org.springframework.orm.hhibernate3.HibernateTransactionManager:使用Hibernate3.0版本进行持久化数据时使用
**3-3. TransactionDefinition定义事务隔离级别**
脏读(Dirty Read):一个事务读取了另一个事务未提交的数据,二这个数据是有可能回滚。
不可重复读(Unrepeated Read):在数据库访问中,一个事务范围内两个相同的查询却返回了不同数据。这是由于查询时系统中其它事务修改的提交而提交而引起的。例如:事务B中对某个查询执行两次,当第一个执行完时,事务A对其数据进行了修改。事务B中再次查询时,数据发生了改变。
幻读(Phantom read):指当前事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是想表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好像发生了幻觉一样。


事务隔离级别
DEFAULT:使用后端数据库默认的隔离级别(spring中的选择项)
READ_UNCOMMITED:允许你读取还未提交的改变的数据,可能导致脏,幻,不可重复读。
READ_COMMITED:允许在并发事务已经提交后读取。可防止脏读,单幻读和不可重复读仍可发生。
REPEATABLE_READ:对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏,不可重复读,但幻读仍可能发生
SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏,幻,不可重复读,这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。
**TransactionDefinition定义事务传播行为**
  PROPAGATION_REQUIRED:支持当前事务,如果不存在,就新建一个
  PROPAGATION_SUPPORTS:支持当前事务,如果不存在,就不适用事务
  PROPAGATION_MANDATORY:支持当前事务,如果不存在,抛出异常。
  PROPAGATION_REQUIRES_NEW:如果有事务存在,挂起当前事务,创建一个新的事务
  PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果有事务存在,挂起当前事务
  PROPAGATION_NEVER:以非事务方式运行,如果有事务存在,抛出异常。
  PROPAGATION_NESTED:如果当前事务存在,就嵌套事务执行。
  主要记:PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW,PROPAGATION_NESTED.
  主要解决:业务层之间的方法相互调用,事务怎么传递的问题
**4-1. 转账环境的搭建**
  文件:applicationContext.xml
  <!-- 引入外部属性文件 -->
  <context:property-placeholder location="classpath:jdbc.properties"/>


  <!-- 配置c3p0连接池 -->
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
<property name="driverClass" value="${jdbc.driverClass}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
  </bean>
  
  <!-- 配置DAO的类 -->
  <bean id="accountDao" class="cn.muke.spring.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property><!--类JdbcDaoSupport有个属性dataSource-->
  </bean>
  文件:AccountDaoImpl.java
  public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {
public void outMoney(String out, Double money) {
String sql = "update account set money = money - ? where name = ?";
this.getJdbcTemplate().update(sql,money,out);
}
  }
**5-1. 编程式事务管理**
  1.在AccountService中使用TransactionTemplate
  . TransactionTemplate依赖DataSourceTransactionManager
  . DataSourceTransactionManager依赖DataSource构造
文件:applicationContext.xml
<!-- 配置业务层类 -->
<bean id="accountService" class="cn.muke.spring.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao"/>
<!-- 注入事务管理的模板: -->
<property name="tTemplate" ref="transactionTemplate"/>
</bean>


<!-- 配置DAO的类 -->
<bean id="accountDao" class="cn.muke.spring.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource"></property>
</bean>
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置事务管理模板,Spring为了简化事务管理的代码而提供的类 -->
<bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
<property name="transactionManager" ref="transactionManager"/>
</bean>
  文件:AccountServiceImpl.java
  //注入事务管理的模板
  private TransactionTemplate tTemplate;
  public void settTemplate(TransactionTemplate tTemplate) {
this.tTemplate = tTemplate;
  }


  /** 
   * @param out:转出账号
   * @param in:转入账号
   * @param money:转账金额
   */
  public void transfer(final String out, final String in, final Double money) {
tTemplate.execute(new TransactionCallbackWithoutResult(){
@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
int i=1/0;//如果出现异常,如果没有事务,后面的不会执行
accountDao.inMoney(in, money);

}

});

 }


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 引入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate"><property name="dataSource" ref="dataSource"/></bean> --><!-- 配置业务层类 --><bean id="accountService" class="cn.muke.spring.demo1.AccountServiceImpl"><property name="accountDao" ref="accountDao"/><!-- 注入事务管理的模板: --><property name="tTemplate" ref="transactionTemplate"/></bean><!-- 配置DAO的类 --><bean id="accountDao" class="cn.muke.spring.demo1.AccountDaoImpl"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 配置事务管理模板,Spring为了简化事务管理的代码而提供的类 --><bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"><property name="transactionManager" ref="transactionManager"/></bean></beans>


package cn.muke.spring.demo1;import org.springframework.transaction.TransactionStatus;import org.springframework.transaction.support.TransactionCallbackWithoutResult;import org.springframework.transaction.support.TransactionTemplate;/** *  * @author Administrator * */public class AccountServiceImpl implements AccoutService {//注入转账的DAO的类private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}//注入事务管理的模板private TransactionTemplate tTemplate;public void settTemplate(TransactionTemplate tTemplate) {this.tTemplate = tTemplate;}/** *  * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */public void transfer(final String out, final String in, final Double money) {tTemplate.execute(new TransactionCallbackWithoutResult(){@Overrideprotected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {accountDao.outMoney(out, money);int i=1/0;//如果出现异常,如果没有事务,后面的不会执行accountDao.inMoney(in, money);}});}}



**6-1. 声明式事务管理方式一:基于TransactionProxyFactoryBean的方式**
  文件:applicationContext.xml
  <!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 配置业务层的代理: -->
<bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<!-- 配置目标对象 -->
<property name="target" ref="accountService"/>
<!-- 注入事务管理器, -->
<property name="transactionManager" ref="transactionManager"/>
<!-- 注入事务属性 -->
<property name="transactionAttributes">
<props>
<!-- 方法名称,prop的格式 
*PROPAGATION:事务的传播行为
*ISOLATION:事务的隔离级别
*READONLY:只读(不可以进行修改,插入,删除)
*-Exception:发生哪些异常,回滚事务
*+Exception:发生哪些异常,不回滚事务
-->
<!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.Exception</prop> 出现异常,不回滚事务-->
<!-- <prop key="transfer">PROPAGATION_REQUIRED,readonly</prop> 不可以进行修改,插入,删除-->
<prop key="transfer">PROPAGATION_REQUIRED</prop>
</props>
</property>
</bean>
测试:
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:applicationContext2.xml"})
public class AccountServiceImplTest {
/**
* 注入代理类,进行增强的操作
*/
@Resource(name="accountServiceProxy")
private AccoutService accoutService;
@Test
public void testTransfer() {
//AccoutService as=(AccoutService)ac.getBean("accountService");
accoutService.transfer("aaa", "bbb", 13.0);
}

}

<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 引入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- 配置业务层类 --><bean id="accountService" class="cn.muke.spring.demo2.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!-- 配置DAO的类 --><bean id="accountDao" class="cn.muke.spring.demo2.AccountDaoImpl"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 配置业务层的代理: --><bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"><!-- 配置目标对象 --><property name="target" ref="accountService"/><!-- 注入事务管理器, --><property name="transactionManager" ref="transactionManager"/><!-- 注入事务属性 --><property name="transactionAttributes"><props><!-- 方法名称,prop的格式 *PROPAGATION:事务的传播行为*ISOLATION:事务的隔离级别*READONLY:只读(不可以进行修改,插入,删除)*-Exception:发生哪些异常,回滚事务*+Exception:发生哪些异常,不回滚事务--><!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.Exception</prop> 出现异常,不回滚事务--><!-- <prop key="transfer">PROPAGATION_REQUIRED,readonly</prop> 不可以进行修改,插入,删除--><prop key="transfer">PROPAGATION_REQUIRED</prop></props></property></bean></beans>


package cn.muke.spring.demo2;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;import cn.muke.spring.demo2.AccoutService;/** * spring声明式事务的方式 * @author Administrator * */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext2.xml"})public class AccountServiceImplTest {/** * 注入代理类,进行增强的操作 *///@Resource(name="accountService")@Resource(name="accountServiceProxy")private AccoutService accoutService;@Testpublic void testTransfer() {//AccoutService as=(AccoutService)ac.getBean("accountService");accoutService.transfer("aaa", "bbb", 13.0);}}



**6-2. 声明式事务管理方式二:基于AspectJ的XMl方式**
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>


<!-- 配置事务的通知:(事务的增强) -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 
propagation:事务传播行为
isolation:事务隔离级别
read-only:只读
rollback-for:发生哪些异常回滚。
no-rollback-for:发生哪些异常不回滚
timeout:过期信息

-->
<tx:method name="transfer" propagation="REQUIRED"/>
</tx:attributes>
</tx:advice>


<!-- 配置切面 -->
<aop:config>
<!-- 配置切入点 ,+意思是:AccountService的子类-->
<aop:pointcut expression="execution(* cn.muke.spring.demo3.AccoutService+.*(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>


测试类:AccountServiceImplTest.java
@Resource(name="accountService")
private AccoutService accountService;


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 引入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- 配置业务层类 --><bean id="accountService" class="cn.muke.spring.demo3.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!-- 配置DAO的类 --><bean id="accountDao" class="cn.muke.spring.demo3.AccountDaoImpl"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 配置事务的通知:(事务的增强) --><tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><!-- propagation:事务传播行为isolation:事务隔离级别read-only:只读rollback-for:发生哪些异常回滚。no-rollback-for:发生哪些异常不回滚timeout:过期信息 --><tx:method name="transfer" propagation="REQUIRED"/></tx:attributes></tx:advice><!-- 配置切面 --><aop:config><!-- 配置切入点 ,+意思是:AccountService的子类--><aop:pointcut expression="execution(* cn.muke.spring.demo3.AccoutService+.*(..))" id="pointcut1"/><!-- 配置切面 --><aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/></aop:config></beans>


测试类

package cn.muke.spring.demo3;import javax.annotation.Resource;import org.junit.Test;import org.junit.runner.RunWith;import org.springframework.test.context.ContextConfiguration;import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;/** * Spring的声明式事务管理的方式二:基于AspectJ的XML方式的配置 * @author Administrator * */@RunWith(SpringJUnit4ClassRunner.class)@ContextConfiguration(locations={"classpath:applicationContext3.xml"})public class AccountServiceImplTest {@Resource(name="accountService")private AccoutService accountService;@Testpublic void testTransfer() {accountService.transfer("aaa", "bbb", 12.0);}}



**6-3. 声明式事务管理方式三:基于注解的方式
<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>
文件 AccountServiceImpl.java
/**
 * 
 * @author Administrator
 *@Transactional注解中的属性:
 *propagation:事务的传播行为
 *isolation:事务的隔离级别
 *readOnly:只读
 *rollbackFor:发生异常回滚
 *noRollbackFor:发生哪些异常不回滚
 */
@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)
public class AccountServiceImpl ....


<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns:context="http://www.springframework.org/schema/context"xmlns:aop="http://www.springframework.org/schema/aop"xmlns:tx="http://www.springframework.org/schema/tx"xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsdhttp://www.springframework.org/schema/contexthttp://www.springframework.org/schema/context/spring-context.xsdhttp://www.springframework.org/schema/aophttp://www.springframework.org/schema/aop/spring-aop.xsdhttp://www.springframework.org/schema/txhttp://www.springframework.org/schema/tx/spring-tx.xsd"><!-- 引入外部属性文件 --><context:property-placeholder location="classpath:jdbc.properties"/><!-- 配置c3p0连接池 --><bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"><property name="driverClass" value="${jdbc.driverClass}"/><property name="jdbcUrl" value="${jdbc.url}"/><property name="user" value="${jdbc.username}"/><property name="password" value="${jdbc.password}"/></bean><!-- 配置业务层类 --><bean id="accountService" class="cn.muke.spring.demo4.AccountServiceImpl"><property name="accountDao" ref="accountDao"/></bean><!-- 配置DAO的类 --><bean id="accountDao" class="cn.muke.spring.demo4.AccountDaoImpl"><property name="dataSource" ref="dataSource"></property></bean><!-- 配置事务管理器 --><bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"><property name="dataSource" ref="dataSource"/></bean><!-- 开启注解事务 --><tx:annotation-driven transaction-manager="transactionManager"/></beans>




package cn.muke.spring.demo4;import org.springframework.transaction.annotation.Isolation;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;/** *  * @author Administrator *@Transactional注解中的属性: *propagation:事务的传播行为 *isolation:事务的隔离级别 *readOnly:只读 *rollbackFor:发生异常回滚 *noRollbackFor:发生哪些异常不回滚 */@Transactional(propagation=Propagation.REQUIRED,isolation=Isolation.DEFAULT,readOnly=false)public class AccountServiceImpl implements AccoutService {//注入转账的DAO的类private AccountDao accountDao;public void setAccountDao(AccountDao accountDao) {this.accountDao = accountDao;}/** *  * @param out:转出账号 * @param in:转入账号 * @param money:转账金额 */public void transfer(String out, String in, Double money) {accountDao.outMoney(out, money);int i=1/0;//如果出现异常,如果没有事务,后面的不会执行accountDao.inMoney(in, money);}}




  






  
0 0
原创粉丝点击