6.4 声明式事务

来源:互联网 发布:csol mac 编辑:程序博客网 时间:2024/06/06 04:37

Spring提供了3钟方式来声明事务式边界:

1、TransactionProxyFactoryBean的代理Bean来实现声明式事务。

2、使用Spring的tx命名空间

3、@Transaction注解

6.4.1 定义事务属性

在Spring中,声明式事务是通过事务属性来定义的。事务属性包含了5个方面:

1、传播行为

2、隔离级别

3、是否只读

4、事务超时

5、回滚规则

传播行为

事务的第一个方面是传播行为(propagation behavior)。传播行为定义了客户端与被调用方法之间的事务边界。

传播规则回答了这样一个问题,即新的事务应该被启动还是被挂起,或者方法是否要在事务环境中运行。

表:传播规则定义了何时要创建一个事务或何时使用已有的事务。Spring提供了多种传播规则供选择。

传播行为含义PROPAGATION_MANDATORYPROPAGATION_NESTEDPROPAGATION_NEVERPROPAGATION_NOT_SUPPORTEDPROPAGATION_REQUIREDPROPAGATION_REQUIRES_NEWPROPAGATION_SUPPORTS
隔离级别(isolation level)

隔离级别定义了一个事务可能受其他并发事务影响的程度。另一种考虑隔离级别的方式就是将其想象成事务对于事务性数据的自私程度。

多个事务并发可能导致的问题:脏读、不可重复读、幻读。

表:隔离级别决定了一个事务会被其他并行的事务所能影响的程度

隔离级别含义ISOLATION_DEFAULTISOLATION_READ_UNCOMMITTEDISOLATION_READ_COMMITTEDISOLATION_REPEATABLE_READISOLATION_SERIALIZABLE

只读

声明式事务的第三个特性是它是否为只读事务


事务超时

事务不能运行太长的时间


回滚规则

定义了哪些异常会导致事务回滚而哪些不会。


6.4.2 在XML中定义事务

使用tx命名空间会涉及将其添加到Spring XML配置文件中

<span style="font-size:18px;"><beans xmlns="http://www.springframework.org/schema/beans" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xsi:schemaLocation="http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsdhttp://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsdhttp://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsdhttp://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"></span>

<tx:advice>声明事务性策略:

<span style="font-size:18px;"><tx:advice id="txAdvice">     <tx:attributes>       <tx:method name="add*" propagation="REQUIRED" />       <tx:method name="save*" propagation="REQUIRED" />       <tx:method name="*" propagation="SUPPORTS"           read-only="true"/>     </tx:attributes>   </tx:advice> </span>

表:事务五边形的5个方面通过该元素的属性来指定

属性含义isolation指定事务的隔离级别propagation指定事务的传播规则read-only指定事务为只读回滚规则:                                                                                 rollback-for                                                                                        no-rollback-for                                         rollback-for指定事务对于哪些检查型异常应当回滚而不提交                                                                                            no-roollback-for指定事务对于哪些异常应当继续运行而不回滚                                     timeout对于长时间运行的事务定义超时时间

<tx:advice>假定事务管理器被声明为一个id为transactionManaget的Bean,如果不是,则需要明确指定事务管理器的id:

<tx:advice id="txAdvice" transaction-manager="txManaget">

     ...

</tx:advice>


在<tx:advice>中没有声明哪些Bean应该被通知——我们需要一个切点来做这件事。为了完整定义事务性切面,必须定义一个通知器(advisor):

通知所有实现SpitterService接口的Bean:

<aop:config>    <aop:advisor         pointcut="execution(* *..SpitterService.*(..))"        advice-ref="txAdvice" />  </aop:config>

6.4.3 定义注解驱动的事务

使用<tx:annotation-driven>时,只需要一行XML:

 <tx:annotation-driven />

指定特定的事务管理期:(默认值为transactionManager)

 <tx:annotation-driven transaction-manager="txManager" />


扫描组件

 <context:component-scan 
      base-package="com.habuma.spitter.service" />

包含@Transactional注解的SpitterServiceImpl

package com.habuma.spitter.service;import static java.lang.Math.*;import static java.util.Collections.*;import java.util.Date;import java.util.List;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import org.springframework.transaction.annotation.Propagation;import org.springframework.transaction.annotation.Transactional;import com.habuma.spitter.domain.Spitter;import com.habuma.spitter.domain.Spittle;import com.habuma.spitter.persistence.SpitterDao;@Service("spitterService")@Transactional(propagation=Propagation.REQUIRED)public class SpitterServiceImpl implements SpitterService {  public void saveSpittle(Spittle spittle) {    spittle.setWhen(new Date());    spitterDao.saveSpittle(spittle);  }  @Transactional(propagation=Propagation.SUPPORTS, readOnly=true)  public List<Spittle> getRecentSpittles(int count) {    List<Spittle> recentSpittles =         spitterDao.getRecentSpittle();        reverse(recentSpittles);        return recentSpittles.subList(0,             min(49, recentSpittles.size()));  }    public void saveSpitter(Spitter spitter) {    if(spitter.getId() == null) {      spitterDao.addSpitter(spitter);    } else {      spitterDao.saveSpitter(spitter);    }  }    @Transactional(propagation=Propagation.SUPPORTS, readOnly=true)  public Spitter getSpitter(long id) {    return spitterDao.getSpitterById(id);  }  public void startFollowing(Spitter follower, Spitter followee) {    // TODO Auto-generated method stub    }    public List<Spittle> getSpittlesForSpitter(Spitter spitter) {    return spitterDao.getSpittlesForSpitter(spitter);  }  public List<Spittle> getSpittlesForSpitter(String username) {    Spitter spitter = spitterDao.getSpitterByUsername(username);    return getSpittlesForSpitter(spitter);  }  public Spitter getSpitter(String username) {    return spitterDao.getSpitterByUsername(username);  }  public void deleteSpittle(long id) {    spitterDao.deleteSpittle(id);  }    public List<Spitter> getAllSpitters() {    return spitterDao.findAllSpitters();  }  @Autowired  SpitterDao spitterDao;  public Spittle getSpittleById(long id) {    return spitterDao.getSpittleById(id);  }}




















0 0