Spring1.x使用TransactionProxyFactoryBean创建事务代理

Spring同时支持编程式事务策略和声明式事务策略,在实际开发中,几乎都采用声明式事务策略。使用 声明式事务策略的优势 十分明显:

① 声明式事务能大大降低开发者的代码书写量,而且声明式事务几乎不影响应用的代码。因此,无论底层事务策略如何变化,应用程序都无须任何改变。

② 应用程序代码无须任何事务处理代码,可以更关注于业务逻辑的实现。

③ Spring可对任何POJO的方法提供事务管理,而且Spring的声明式事务管理无须容器的支持,可在任何环境下使用。

④ EJB的CMT无法提供声明式回滚规则;而通过配置文件,Spring可指定事务在遇到特定异常时自动回滚。Spring不仅可在代码中使用setRollbackOnly回滚事务,也可在配置文件中配置回滚规则。

⑤ 由于Spring采用AOP方式管理事务,因此可以在事务回滚动作中插入用户自己的动作,而不仅仅是执行系统默认的回滚。

在Spring1.x中,声明式事务使用 TransactionProxyFactoryBean 来配置事务代理Bean。每个TransactionProxyFactoryBean为一个目标Bean生成一个事务代理Bean,事务代理的方法改写了目标Bean的方法,就是在目标Bean的方法执行之前加入开始事务,在目标Bean的方法正常结束之后提交事务,如果遇到特定异常则回滚事务。

TransactionProxyFactoryBean创建事务代理时,需要了解当前事务所处的环境,该环境属性通过PlatformTransactionManager实例传入,而相关事务规则则在该Bean定义中给出。

NewsDao.java :

public interface NewsDao {
	public void insert(Integer id,String title,String content);
}
NewsDaoImpl.java :

import javax.sql.DataSource;

import org.springframework.jdbc.core.JdbcTemplate;

public class NewsDaoImpl implements NewsDao{
	
	private DataSource ds;
	
	public void setDs(DataSource ds) {
		this.ds = ds;
	}

	@Override
	public void insert(Integer id, String title, String content) {
		JdbcTemplate jt=new JdbcTemplate(ds);
		jt.update("insert into news values(?,?,?)",new Object[]{id,title,content});
		jt.update("insert into news values(?,?,?)",new Object[]{id,title,content});
	}
	

}
bean.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:tx="http://www.springframework.org/schema/tx"
        xsi:schemaLocation="http://www.springframework.org/schema/beans 
        http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                http://www.springframework.org/schema/context 
                http://www.springframework.org/schema/context/spring-context-2.5.xsd
                http://www.springframework.org/schema/tx 
                http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
    
    <!-- 定义数据源Bean -->
    <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
        <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"/>
        <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl"/>
        <property name="user" value="scott"/>
        <property name="password" value="tiger"/>
        <property name="maxPoolSize" value="40"/>
        <property name="minPoolSize" value="1"/>
        <property name="initialPoolSize" value="1"/>
        <property name="maxIdleTime" value="20"/>
    </bean>
    
    <!-- 配置一个业务逻辑Bean -->
    <bean id="newsDao" class="com.bean.NewsDaoImpl">
        <property name="ds" ref="dataSource"/>
    </bean>
    
    <!-- 配置JDBC数据源的局部事务管理器 -->
    <bean id="transactionManager" 
          class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>
    
    <!-- 为业务逻辑Bean配置事务代理 -->
    <bean id="newsDaoTrans" 
          class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
          <property name="transactionManager" ref="transactionManager"/>
          <property name="target" ref="newsDao"/>
          <property name="transactionAttributes">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
          </property>
    </bean>
    
 </beans>
Test.java :

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.bean.NewsDao;

public class Test {
	
	public static void main(String[] args) {
		ApplicationContext ctx=new ClassPathXmlApplicationContext("bean.xml");
		NewsDao dao=(NewsDao) ctx.getBean("newsDaoTrans");
		dao.insert(1,"夺冠","绿衫军夺冠");
	}
}
运行程序,控制台输出:

查看数据库:

可以知道,插入数据失败。上面程序中违反主键约束,该行代码将引发异常。

如果在没有事务控制的环境下,前一条代码将会向数据表中插入一条记录,第二条插入失败。但是现在一条记录都没有插入,这说明事务起作用了,这两条语句是一个整体,因为第二条插入失败,导致第一条插入的数据也被回滚。

配置事务代理 时需要传入一个事务管理器,一个目标Bean,并指定该事物代理的事务属性,事务属性由transactionAttributes属性指定。上面事务属性只有一条事务传播规则,该规则指定对于所有方法都使用PROPAGATION_REQUIRED的传播规则。Spring支持的事务传播规则如下:

事务传播规则说明
PROPAGATION_MANDATORY要求调用该方法的线程必须处于事务环境中,否则抛出异常。
PROPAGATION_NESTED如果执行该方法的线程已经处于事务环境下,依然启动新的事务,方法在嵌套的事务里执行。如果执行该方法的线程并未处于事务中,也启动新的事务,然后执行该方法,次时与PROPAGATION_REQUIRED相同。
PROPAGATION_NEVER不允许调用该方法的线程处于事务环境下,如果调用该方法的线程处于事务环境下,则抛出异常。
PROPAGATION_NOT_SUPPORTED如果调用该方法的线程处在事务中,则先暂停当前事务,然后执行该方法。
PROPAGATION_REQUIRED要求在事务环境中执行该方法,如果当前执行线程已经处于事务中,则直接调用;如果当前执行线程不处于事务中,则启动新的事务后执行该方法。
PROPAGATION_REQUIRES_NEW该方法要求在新的事务环境中执行,如果当前执行线程已经处于事务中,则先暂停当前事务,启动新事务后执行该方法;如果当前调用线程不处于事务中,则启动新的事务后执行方法。
PROPAGATION_SUPPORTS如果当前执行线程处于事务中,则使用当前事务,否则不使用事务。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值