使用Spring进行事物管理

来源:互联网 发布:js 页面跳转 禁止后退 编辑:程序博客网 时间:2024/04/29 10:15

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;@BeforeClasspublic 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来进行事物管理器测试 */@Testpublic 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  */@Testpublic void testPlatformTransactionManagerForLowLevel() {DefaultTransactionDefinition def=new DefaultTransactionDefinition();def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);TransactionStatus status=txManager.getTransaction(def);//因為我用的是Oracle,所以下面用OracleConnectionOracleConnection 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回调接口指定 * 每天有事物管理代码,而是由模板类来完成事物管理,这样简单多了 */@Testpublic void testTransactionTemplate(){TransactionTemplate transactionTemplate=new TransactionTemplate(txManager);transactionTemplate.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);transactionTemplate.execute(new TransactionCallbackWithoutResult(){@Overrideprotected 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 0
原创粉丝点击