spring总结(三十)--编程式事务

来自:https://blog.csdn.net/liaohaojian/article/details/70139151

2.编程式事务:编码方式实现事务管理(代码演示为JDBC事务管理)

Spring实现编程式事务,依赖于2大类,分别是上篇文章提到的PlatformTransactionManager,与模版类TransactionTemplate(推荐使用)。下面分别详细介绍Spring是如何通过该类实现事务管理。
1)PlatformTransactionManager,上篇文章已经详情解说了该类所拥有的方法,不记得可以回看上篇文章。
 

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
	<property name="jdbcUrl" value="${db.jdbcUrl}" />
	<property name="user" value="${user}" />
	<property name="password" value="${password}" />
	<property name="driverClass" value="${db.driverClass}" />
	 <!--连接池中保留的最小连接数。 --> 
     <property name="minPoolSize"> 
         <value>5</value> 
     </property> 
     <!--连接池中保留的最大连接数。Default: 15 --> 
     <property name="maxPoolSize"> 
         <value>30</value> 
     </property> 
     <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> 
     <property name="initialPoolSize"> 
         <value>10</value> 
     </property> 
     <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> 
     <property name="maxIdleTime"> 
         <value>60</value> 
     </property> 
     <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> 
     <property name="acquireIncrement"> 
         <value>5</value> 
     </property> 
     <!--JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。  如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 --> 
     <property name="maxStatements"> 
         <value>0</value> 
     </property> 
     <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> 
     <property name="idleConnectionTestPeriod"> 
         <value>60</value> 
     </property> 
     <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> 
     <property name="acquireRetryAttempts"> 
         <value>30</value> 
     </property> 
     <!--获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。Default: false --> 
     <property name="breakAfterAcquireFailure"> 
         <value>true</value> 
     </property> 
     <!--因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable等方法来提升连接测试的性能。Default: false --> 
     <property name="testConnectionOnCheckout"> 
         <value>false</value> 
     </property> 
</bean>
<!--DataSourceTransactionManager位于org.springframework.jdbc.datasource包下,数据源事务管理类,提供对单个javax.sql.DataSource数据源的事务管理,主要用于JDBC,Mybatis框架事务管理。 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<property name="dataSource" ref="dataSource" />
</bean>

业务中使用代码(以测试类展示)

import java.util.Map;
import javax.annotation.Resource;
import javax.sql.DataSource;
import org.apache.log4j.Logger;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;
 
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:spring-public.xml" })
public class test {
	@Resource
	private PlatformTransactionManager txManager;
	@Resource
	private  DataSource dataSource;
	private static JdbcTemplate jdbcTemplate;
	Logger logger=Logger.getLogger(test.class);
    private static final String INSERT_SQL = "insert into testtranstation(sd) values(?)";
    private static final String COUNT_SQL = "select count(*) from testtranstation";
	@Test
	public void testdelivery(){
		//定义事务隔离级别,传播行为,
	    DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
	    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
	    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);  
	    //事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
	    TransactionStatus status = txManager.getTransaction(def);  
	    jdbcTemplate = new JdbcTemplate(dataSource);
	    int i = jdbcTemplate.queryForInt(COUNT_SQL);  
	    System.out.println("表中记录总数:"+i);
	    try {  
	        jdbcTemplate.update(INSERT_SQL, "1");  
	        txManager.commit(status);  //提交status中绑定的事务
	    } catch (RuntimeException e) {  
	        txManager.rollback(status);  //回滚
	    }  
	    i = jdbcTemplate.queryForInt(COUNT_SQL);  
	    System.out.println("表中记录总数:"+i);
	}
	
}

2)使用TransactionTemplate,该类继承了接口DefaultTransactionDefinition,用于简化事务管理,事务管理由模板类定义,主要是通过TransactionCallback回调接口或TransactionCallbackWithoutResult回调接口指定,通过调用模板类的参数类型为TransactionCallback或TransactionCallbackWithoutResult的execute方法来自动享受事务管理。

TransactionTemplate模板类使用的回调接口:

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

@Test
public void testTransactionTemplate(){
	jdbcTemplate = new JdbcTemplate(dataSource);
    int i = jdbcTemplate.queryForInt(COUNT_SQL);  
    System.out.println("表中记录总数:"+i);
	//构造函数初始化TransactionTemplate
	TransactionTemplate template = new TransactionTemplate(txManager);
	template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
	//重写execute方法实现事务管理
	template.execute(new TransactionCallbackWithoutResult() {
		@Override
		protected void doInTransactionWithoutResult(TransactionStatus status) {
			jdbcTemplate.update(INSERT_SQL, "饿死");   //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
		}}
	);
	i = jdbcTemplate.queryForInt(COUNT_SQL);  
    System.out.println("表中记录总数:"+i);
}

 

3.声明式事务:可知编程式事务每次实现都要单独实现,但业务量大功能复杂时,使用编程式事务无疑是痛苦的,而声明式事务不同,声明式事务属于无侵入式,不会影响业务逻辑的实现。

spring是轻量级框架的因为他是非侵入式的:基于 Spring 开发的应用中的对象可以不依赖于 Spring 的 API

猜你喜欢

转载自blog.csdn.net/lsx2017/article/details/84844585