spring 事务详解

                                                        spring事务详解

1.什么是事务

       所谓事务是用户定义的一个数据库操作序列,这些操作要么全做,要么全不做,是一个不可分割的工作单位。

2.事务的特性

原子性:要么全做,要么全不做。

一致性:说的是全部做,和全不做,这时数据库处于一致性,如果一个做,一个不做,就认为不一致。

隔离性:一个事务的执行不能被其他事务干扰,即一个事务的内部操作以及使用的数据对其他并发事务是隔离的。

持续性:一个事务一旦提交,它对数据库中数据的改变就应该是永久行的。、

3.事务并带来哪些问题

  3.1丢失修改

         两个事务T1和T2读入同一个数据并修改,T2提交的结果破坏了T1提交的结果,导致T1的修改被丢失。

  3.2不可重复读

         事务T1读取数据后,事务T2执行更新操作,使得T1无法再现前一次读到的结果。

  3.3读脏数据

        T1修改某一个数据并将其写回磁盘,事务T2读到T1修改之后的数据,这时T1由于某种原因被撤销,数据恢复到原来的值,T1读到的数据为脏数据。

  3.4幻读

       事务T1读取数据后,事务T2执行插入操作,T1再次读取,使T1出现了幻觉。

4.事务的API介绍

   4.1 事务管理器PlatformTransactionManager


spring为不同的持久化框架提供了不同的PlatformTransactionManager


   4.2 TransactionDefinition事务定义信息(隔离,传播,超时,只读)

       4.2.1 隔离级别

设置隔离级别可防止并发导致的问题。


如果选择DEFAULT则是数据库默认的隔离级别。

mysql 默认REPEATABLE_READ

oracle默认 READ_COMMITTED

  4.2.2 事务的传播行为


  4.2.3 TransactionStatus事务具体运作状态

void flush();冲洗数据库底层会话

boolean hasSavePoint();返回该事务是否有一个保存点

boolean isCompleted();返回事务是否提交或者回滚

boolean isNewTransaction();返回是否是一个新事务

boolean isRollbackOnly();判断这个事务是否已经设置了rollback-only。

void setRollbackOnly();设置这个事务rollback-only。

4.2.4 SavepointManager
 
事务回滚点管理接口,提供创建、释放回滚点,或者回滚到指定的回滚点。
 
 方法摘要:
 Object createSavepoint()
          Create a new savepoint.
          创建一个新的回滚点。
 void releaseSavepoint(Object savepoint)
          Explicitly release the given savepoint.
          释放一个给定的回滚点。
 void rollbackToSavepoint(Object savepoint)
          Roll back to the given savepoint.
          回滚到给定的回滚点。

5.银行转账示例

5.1 编程式事务管理

   5.1.1 创建数据库


5.1.2 Dao层

public interface AccountDao {


/**
* @param out :转出账号
* @param money:转账金额
*/
public void outMoney(String out,Double money);

/**
* 
* @param in :转入账号
* @param money:转账金额
*/
public void inMoney(String in,Double money);
}


public class AccountDaoImpl extends JdbcDaoSupport implements AccountDao {


/**
* @param out :转出账号
* @param money:转账金额
*/
@Override
public void outMoney(String out, Double money) {
String sql = "update account set money = money-? where name = ?";
this.getJdbcTemplate().update(sql, money, out);
}


/**
* @param in :转入账号
* @param money:转账金额
*/
@Override
public void inMoney(String in, Double money) {
String sql = "update account set money = money+? where name = ?";
this.getJdbcTemplate().update(sql,money,in);
}


}


5.1.3 Service层

public interface AccountService {


/**
* @param out :转出账号
* @param in :转入账号
* @param money:转账金额
*/
public void transfer(String out,String in,Double money);
}


public class AccountServiceImpl implements AccountService {

//注入转账的DAO
private AccountDao accountDao;


//注入事务管理的模板
private TransactionTemplate transactionTemplate;


/**
* @param out :转出账号
* @param in :转入账号
* @param money:转账金额
*/
@Override
public void transfer(final String out, final String in, final Double money) {
/*accountDao.outMoney(out, money);
//int i = 1/0;
accountDao.inMoney(in, money);*/

//
transactionTemplate.execute(new TransactionCallbackWithoutResult() {


@Override
protected void doInTransactionWithoutResult(TransactionStatus transactionStatus) {
accountDao.outMoney(out, money);
//int i = 1/0;
accountDao.inMoney(in, money);
}
});
}


public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}


public void setTransactionTemplate(TransactionTemplate transactionTemplate) {
this.transactionTemplate = transactionTemplate;
}


}


5.1.4 xml配置

<?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"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.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="com.zs.spring.demo1.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
<!-- 注入事务管理的模板 -->
<property name="transactionTemplate" ref="transactionTemplate" />
</bean>

<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 配置DAO类(未简化) -->
<!-- <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
<bean id="accountDao" class="com.zs.spring.demo1.AccountDaoImpl">
<property name="jdbcTemplate" ref="jdbcTemplate" />
</bean> -->

<!-- ==================================1.编程式的事务管理=============================================== -->
<!-- 配置事务管理器 -->
<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>


5.1.5 测试类

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext1.xml")
public class TransactionTest {


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

@Test
public void demo1(){
accountService.transfer("aaa", "bbb", 200d);
}
}



5.2 使用xml配置申明式事务管理

代码侵入性小,是通过spring aop 实现的。

   5.2.1 使用XML配置声明式的事务管理(原始方式)

Service层的变化

 public class AccountServiceImpl implements AccountService {

//注入转账的DAO
private AccountDao accountDao;
public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}


/**
* @param out :转出账号
* @param in :转入账号
* @param money:转账金额
*/
@Override
public void transfer( String out, String in, Double money) {
accountDao.outMoney(out, money);
//int i = 1/0;
accountDao.inMoney(in, money);

}

}

xml的变化

<?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"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.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="com.zs.spring.demo2.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>

<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo2.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- ==================================2.使用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>
<!-- 注入事务的属性 -->
<property name="transactionAttributes">
<props>
<!-- 
prop的格式:
* PROPAGATION :事务的传播行为
* ISOTATION :事务的隔离级别
* readOnly :只读
* -EXCEPTION :发生哪些异常回滚事务
* +EXCEPTION :发生哪些异常不回滚事务
-->
<prop key="transfer">PROPAGATION_REQUIRED</prop>
<!-- <prop key="transfer">PROPAGATION_REQUIRED,readOnly</prop> -->
<!-- <prop key="transfer">PROPAGATION_REQUIRED,+java.lang.ArithmeticException</prop> -->
</props>
</property>
</bean>


</beans>


 test类的变化

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext2.xml")
public class TransactionTest {


/**
* 一定要注入代理类:因为代理类进行增强的操作
*/
//@Resource(name="accountService")
@Resource(name="accountServiceProxy")
private AccountService accountService;

@Test
public void demo1(){
accountService.transfer("aaa", "bbb", 200d);
}
}



5.3 使用XML配置声明式的事务管理,基于tx/aop

  5.3.1 xml配置

<?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"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.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="com.zs.spring.demo3.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>

<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo3.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- ==================================3.使用XML配置声明式的事务管理,基于tx/aop=============================================== -->

<!-- 配置事务管理器 -->
<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>
<!-- 配置切入点 -->
<aop:pointcut expression="execution(* com.zs.spring.demo3.AccountService+.*(..))" id="pointcut1"/>
<!-- 配置切面 -->
<aop:advisor advice-ref="txAdvice" pointcut-ref="pointcut1"/>
</aop:config>


</beans>


5.3.2 test的变化

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:applicationContext3.xml")
public class TransactionTest {



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

@Test
public void demo1(){
accountService.transfer("aaa", "bbb", 200d);
}
}


5.4 事务注解的实现

    5.4.1 xml配置

<?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"
     xmlns:task="http://www.springframework.org/schema/task"
     xsi:schemaLocation="http://www.springframework.org/schema/beans
         http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
         http://www.springframework.org/schema/context
         http://www.springframework.org/schema/context/spring-context-3.1.xsd
         http://www.springframework.org/schema/aop
         http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
         http://www.springframework.org/schema/tx
         http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
         http://www.springframework.org/schema/task
http://www.springframework.org/schema/task/spring-task-3.1.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="com.zs.spring.demo4.AccountServiceImpl">
<property name="accountDao" ref="accountDao" />
</bean>

<!-- 配置DAO类(简化,会自动配置JdbcTemplate) -->
<bean id="accountDao" class="com.zs.spring.demo4.AccountDaoImpl">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- ==================================4.使用注解配置声明式事务============================================ -->


<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource" />
</bean>

<!-- 开启注解事务 -->
<tx:annotation-driven transaction-manager="transactionManager"/>

</beans>


5.4.2 Serverce

 *@Transactional(Propagation.REQUIRED)中的的属性
 *propagation :事务的传播行为
 *isolation :事务的隔离级别
 *readOnly :只读
 *rollbackFor :发生哪些异常回滚
 *noRollbackFor :发生哪些异常不回滚
 *rollbackForClassName 根据异常类名回滚
 */
@Transactional
public class AccountServiceImpl implements AccountService {

//注入转账的DAO
private AccountDao accountDao;



/**
* @param out :转出账号
* @param in :转入账号
* @param money:转账金额
*/
@Override
public void transfer( String out, String in, Double money) {
accountDao.outMoney(out, money);
//int i = 1/0;
accountDao.inMoney(in, money);

}


public void setAccountDao(AccountDao accountDao) {
this.accountDao = accountDao;
}
}

















  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

醒悟wjn

打赏可获取源码

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值