使用Spring进行事物管理

1、编程式事物

所谓编程式事物指的是通过编码方式实现事物,即类似于JDBC编程实现事物管理

Spring对编程式事物的支持

Spring中的事物可以分为物理事物和逻辑事物;

        物理事物:就是底层数据库提供的事物支持,如JDBC或JTA提供的事物;

       逻辑事物:是Spring管理的事物,不同于物理事物,逻辑事物提供更丰富的控制而且如果想得到Spring事务管理的好处必须使用逻辑事务,因此在Spring中如果没特别强调        一般就是逻辑事务

Spring提供两种编程式事物支持:直接使用PlatformTransactionManager实现和使用TransactionTemplate模板类,用于支持逻辑事物管理。

1.1、直接使用PlatformTransactionTemplateManager进行编程式事物管理

PlatformTransactionTemplateManager实现,然后结合TransactionDefinition开启事物,并结合TransactionStatus来回滚或提交事物,就可以完成针对当前对象的整个事物管理

使用它的缺点也是很明显的,从应用程序开发的角度看,过于底层,不同事物管理API的造成的差异太大,异常处理会变得很麻烦,代码重复的数量将是惊人的。

下面是我使用PlatformTransactionTemplateManager来实现事物管理:

1、数据源和事物管理器定义的配置文件

         <!-- datasource for oracle -->
	<bean id="dataSource"
		class="org.springframework.jdbc.datasource.DriverManagerDataSource"
		destroy-method="close">
		<property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"></property>
		<property name="url" value="jdbc:oracle:thin:@localhost:1521:orcl"></property>
		<property name="username" value="scott"></property>
		<property name="password" value="123"></property>
	</bean>

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

2、测试时使用的SQL:

 public class springTransactionTest {
	/**
	 * 准备好测试使用的sql
	 */
	private static final String INSERT_SQL = "insert into td(user_name,password) values (?,?)";
	private static final String COUNT_SQL = "select count(*) from td";

3、初始化Spring容器:

/**
	 * 初始化spring容器
	 */
	private static ApplicationContext ctx;
	private static PlatformTransactionManager txManager;
	private static DataSource dataSource;
	private static JdbcTemplate jdbcTemplate;

	@BeforeClass
	public static void setUpClass() {
		ctx = new ClassPathXmlApplicationContext("/applicationContext.xml");
		txManager = (PlatformTransactionManager) ctx.getBean("transactionManager");
		dataSource = (DataSource) ctx.getBean("dataSource");
		jdbcTemplate = new JdbcTemplate(dataSource);
	}	

4、使用高级别JdbcTemplate来进行事务管理器测试

/**
	 * 使用高级别JdbcTemplate来进行事物管理器测试
	 */
	@Test
	public void testPlatformTransactionManager() {
		
		/**
		 * DefaultTransactionDefinition:事务定 义,定义如隔离级别、传播行为等,即在本示例中隔离级别为ISOLATION_READ_COMMITTED(提交读),
		 * 传播行为为 PROPAGATION_REQUIRED(必须有事务支持,即如果当前没有事务,就新建一个事务,如果已经存在一个事务中,就加入到这个事务中)。
		 * dbcTemplate:通过JdbcTemplate对象执行相应的SQL操作,且自动享受到事务支持,注意事务是线程绑定的,因此事务管理器可以运行在多线程环境;
		 * txManager.commit(status):提交status对象绑定的事务;
		 * txManager.rollback(status):当遇到异常时回滚status对象绑定的事务。
		 * TransactionStatus:事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来                 * 决定如何开启事务;
		 */
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		/**
		 * getTransaction开启一个事物
		 */
		TransactionStatus status = txManager.getTransaction(def);
		try {
			System.out.println(jdbcTemplate.queryForInt(COUNT_SQL));
			txManager.commit(status);
		} catch (RuntimeException e) {
			txManager.rollback(status);
		}
	}


5、使用低级别解决方案进行事务管理器的测试

         /**
	 * 使用低级别解决方案来进行事物管理器测试
	 * @throws SQLException 
	 */
	@Test
	public void testPlatformTransactionManagerForLowLevel() {
		DefaultTransactionDefinition def=new DefaultTransactionDefinition();
		def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status=txManager.getTransaction(def);
		//因為我用的是Oracle,所以下面用OracleConnection
		OracleConnection conn= (OracleConnection) DataSourceUtils.getConnection(dataSource);
		try {
			PreparedStatement ps=conn.prepareStatement(INSERT_SQL);
			ps.setString(1, "ccc");
			ps.setString(2, "222");
			ps.execute();
			txManager.commit(status);  //之前没有提交的时候数据库里面一直插不进数据,原来需要提交,多谢师弟提醒,好好向别人学习
		} catch (Exception e){  //因为我插入了很多此,但是一直没提交,所以id增加到了43,但是提交的结果是随后一次提交的结果
			 status.setRollbackOnly();  
		      txManager.rollback(status); 
		}finally{
			DataSourceUtils.releaseConnection(conn, dataSource);
		}
	}	

低级别方案中使用DataSourceUtils获取和释放连接,使用txManager开管理事务,而且面向JDBC编程,比起模板类方式来繁琐 和复杂的多,因此不推荐使用该方式


1.2、使用TransactionTemplate进行编程式事物管理

于使用PlatformTransactionManager进行事物管理的流程是固定的,各个事物管理期间只有部分逻辑存在差异,可以考虑像Springde的数据访问层那样,使用模板方法模式与Callback相结合的方式,对直接使用PlatformTransactionManager进行事物管理的代码进行封装,这样就有了更加方便的编程式事物管理方式,即使用TransactionTemplate的编程式事物管理。org.springframework.transaction.support.TransactionTemplate对与PlatformTransactionManager相关的事物界定操作以及相关的异常处理进行了模板化封装,开发人员更多的关注于通过相应的Callback接口提供具体的事物界定内容即可。Spring针对TransactionTemplate提供了两个Callback回调接口

TransactionCallback:通过实现该接口的“T doInTransaction(TransactionStatus status) ”方法来定义需要事务管理的操作代码TransactionCallbackWithoutResult:继承TransactionCallback接口,提供“void doInTransactionWithoutResult(TransactionStatus status)”便利接口用于方便那些不需要返回值的事务操作代码。

下面是的TransactionTemplate模板类的使用:

         /**
	 * 使用TransactionTemplate  模板类用于简化事物管理,事物管理由模板类定义
	 * 具体操作由TransactionCallback接口或TransactionCallbackWithoutResult回调接口指定
	 * 每天有事物管理代码,而是由模板类来完成事物管理,这样简单多了
	 */
	@Test
	public void testTransactionTemplate(){
		TransactionTemplate transactionTemplate=new TransactionTemplate(txManager);
		transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
		transactionTemplate.execute(new TransactionCallbackWithoutResult(){

			@Override
			protected void doInTransactionWithoutResult(TransactionStatus arg0) {
				//jdbcTemplate.update(INSERT_SQL,"jc","333");
				jdbcTemplate.update(INSERT_SQL, new Object[]{"jc","333"});
			}
		});
	}	

TransactionTemplate :通过new TransactionTemplate(txManager)创建事务模板类,其中构造器参数为PlatformTransactionManager 实现,并通过其相应方法设置事务定义,如事务隔离级别、传播行为等,此处未指定传播行为,其默认为PROPAGATION_REQUIRED;

TransactionCallbackWithoutResult:此处使用不带返回的回调实现,其doInTransactionWithoutResult方法实现中定义了需要事务管理的操作;

transactionTemplate.execute():通过该方法执行需要事务管理的回调。


对于JTA的分布式事物这里我没有实现。感觉太麻烦了
通过上面的实践,我基本会使用PlatformTransactionManager和TransactionTemplate进行简单事务处理了,那如何应用到实际项目中去呢?
我将在下篇博客中实现。


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值