`
jieke_ZJ
  • 浏览: 44796 次
  • 性别: Icon_minigender_1
  • 来自: 深圳
社区版块
存档分类
最新评论

spring【事务控制】

 
阅读更多

在开发中需要操作数据库,进行增、删、改操作的过程中属于一次操作,如果在一个业务中需要更新多张表,那么任意一张表的更新失败,整个业务的更新就是失败,这时那些更新成功的表必须回滚,否则业务会出错,这时就要用到事务,即这个业务的操作属于一个事务,事务具有原子性、隔离性、一致性、持续性。这时便用到了事务,事务控制的目的是保证一组操作要么全部成功,要么全部失败。spring提供了对事务的支持,在spring中主要有两种方式使用事务,一、编程式事务控制;二、声明式事务控制。

一、编程式事务控制

所谓编程式事务控制即通过编写代码的方式实现事务的控制。

spring为了方便处理事务,提供了事务管理器,对事务的控制归根到底是通过事务管理器进行控制,在spring中所有的事务控制必须要有事务管理器。下面是一个编程式事务控制的例子,实现账户之间的转账,我们把对事务的控制放在系统的service层(分为controller层、service层、DAO层)来处理,下面是我的spring配置文件,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<?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:aop="http://www.springframework.org/schema/aop"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
    http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"
     
    >
    <!--spring 自动检测-->
     
    <context:component-scan base-package="com.cn.study.day5" />
    <!---->
    <context:property-placeholder location="classpath:db.properties"/>
    <!---->
 
     <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName">
            <value>${db.driver}</value>
        </property>
        <property name="url">
            <value>${db.url}</value>
        </property>
        <property name="username">
            <value>${db.username}</value>
        </property>
        <property name="password">
            <value>123456</value>
        </property>
    </bean>  
     
        <bean id="dao" class="com.cn.study.day5.service.inter.impl.AccountDaoImpl">
         
        <property name="dataSource" ref="dataSource"></property>
    </bean>
     
    <!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
         
    </bean>
    <!--事务管理器模板 方便使用事务-->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>
 
</beans>

  配置了事务管理器,这里使用DataSourceTransactionManager,事务管理器有一个dataSource属性必须配置,这里使用ref属性引用上边的。有了事务管理器之后要使用事务还是比较麻烦,spring又提供了事务管理器模板,我们配置事务管理器模板,事务管理器模板需要一个事务管理器属性,我们引用上边的事务管理器。至此关于编程式的事务控制的配置文件已经准备完毕,下面进行编程式开发。由于,我们把事务控制放在service层,下面是我的service层的代码,

复制代码
package com.cn.study.day5.service.inter.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;

import com.cn.study.day5.service.inter.AccountDaoInter;
import com.cn.study.day5.service.inter.AccountServiceIter;

@Component
public class AccountServiceImpl implements AccountServiceIter {
    @Autowired
    private AccountDaoInter adi;
    @Autowired
    private TransactionTemplate tt;
    //转账方法,由out向in转money元
    @Override
    public void transfer(final String out, final String in, final double money) {
        // TODO Auto-generated method stub

        //使用事务管理器模板进行事务控制
        tt.execute(new TransactionCallbackWithoutResult() {

            @Override
            protected void doInTransactionWithoutResult(TransactionStatus status) {
                // TODO Auto-generated method stub
                adi.outMoney(out, money);
                //一个异常,使用了事务控制,在出现了异常之后,事务会回滚
                int i = 1 / 0;
                adi.inMoney(in, money);
            }
        });

    }

}
复制代码

由于是面向接口编程,这里我只贴出了service层的实现,使用了自动扫描机制(扫描类、属性上的注解@Component、@Autowired),transfer方法是实现转账的方法,首先从一个账户转出,然后转入另一个账户,使用事务管理器模板的execute方法,需要一个TransactionCallBack的实例,这里使用匿名内部类的方式,把要执行的方法放在doInTransactionWithoutResult中执行,保证了事务的控制。

使用这种方式可以保证事务控制,但是在实际开发过程当中这种方式对代码的改动太大,不符合低侵入开发原则,所有这种方式在开发中几乎很少用到,用的最多的是声明式的事务控制。

 

二、声明式事务控制

声明式事务控制又分为三种方式,一、基于TransactionProxyFactoryBean代理的声明式事务控制;二、使用AOP的声明式事务控制;三、基于@Transactional注解的声明式事务控制。

1、基于TransactionProxyFactoryBean的声明式事务控制

TransactionProxyFactoryBean是事务的代理类,spring会为目标类生成一个代理,具体的配置如下,

复制代码
<!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置业务层代理-->
    <bean id="accountServiceProxy" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
        <property name="target" ref="accountServiceImpl"></property>
        <property name="transactionManager" ref="transactionManager"></property>
        <property name="transactionAttributes">
            <props>
                <prop key="transfer"></prop>
            </props>
        </property>
    </bean>
复制代码

这里只贴出了事务管理器和业务层代理的配置,剩余的数据源和业务类的配置可以执行配置,前面说到无论使用哪种方式配置事务管理,都需要使用事务管理器。重点看业务层代理,配置的class属性为TransactionProxyFactoryBean,需要配置三个属性:target(要代理的具体业务层实现类)、transactionManager(事务管理器)、transactionAttributes(要拦截的业务层方法)。配置完成之后,便可以进行测试,测试代码如下,

ApplicationContext ac=getApplicationContext();
        AccountServiceIter asi=(AccountServiceIter)ac.getBean("accountServiceProxy");
        asi.transfer("aa", "cc", 10d);

通过getApplicationContext()方法获得了ApplicationContext实例,然后获得accountServiceProxy的实例,这里获得的不是AccountServiceImpl的实例而是代理的实例对象,因为使用代理,代理了实际的业务类,所有这里不能再使用实际的类而应是代理类。

使用这种方式的需要为每一个需要使用事务的业务类配置一个代理比教麻烦,所以在开发过程中这种方式几乎不用。

2、使用AOP的声明式事务控制

这种方式是在开发过程中使用的比较多的一种,配置如下,

复制代码
<!--配置事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!--配置事务增强-->
    <tx:advice id="advicer" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="transfer*" propagation="REQUIRED"/>
        </tx:attributes>
    </tx:advice>
    <!--配置切点、事务通知-->
    <aop:config>
        <aop:pointcut id="myPointcut" expression="execution(* com.cn.study.day555.service.inter.impl.*.*(..))"/>
        <aop:advisor advice-ref="advicer" pointcut-ref="myPointcut"/>
    </aop:config>
复制代码

配置了事务增强<tx:advice>配置对要增强的方法的事务的传播行为等,配置<aop:config>配置切点和对应的事务通知,这样就完成了AOP的声明式事务控制。

3、基于@Transactional注解

使用@Transactional注解需要再配置文件中开启对这个注解的扫描:<tx:annotation-driven transaction-manager="transactionManager" />,引用了事务管理器,然后就可以使用@Transactional注解,此注解可以使用在类上,也可以使用在方法上,使用在类上即对此类的所有方法都起作用,使用在方法上则表示对单个方法起作用,还可以配置一些属性,放在另一篇文章中进行解释。

通过对以上四种配置事务的方式的描述,其中声明式方式中的第二种方式使用比较普通,对代码的侵入比较小,第三种因为配置简单,也比较常用,但是需要在业务类或方法上加@Transcational注解,对代码有一定的侵入。

分享到:
评论

相关推荐

    spring事务控制

    spring事务控制jar包,请网上自寻下载

    Spring事务控制

    Spring事务控制

    step by step ssh 04 Spring 事务控制

    在"step by step ssh 04 Spring 事务控制"这一主题中,我们将深入探讨如何在SSH架构下实现Spring的AOP(面向切面编程)事务管理,以及如何结合Struts和Hibernate进行用户登录实例。 首先,Struts作为MVC(模型-视图...

    Spring的事务管理小案例

    案例中的"springStudy04_transaction"可能包含了一个使用Spring进行事务管理的简单应用程序,其中可能包括了数据库连接配置、数据访问对象(DAO)的实现以及事务控制的代码。你可以通过阅读源代码来了解如何在实际...

    Spring事务管理Demo

    这种方式灵活性高,但容易导致事务控制代码与业务逻辑混淆,不易维护。 2. **声明式事务管理**:这是Spring最常用的方式,通过在配置文件或者使用`@Transactional`注解来定义事务边界,使得事务管理与业务逻辑分离...

    spring事务与数据库操作

    ### Spring事务与数据库操作 #### 一、Spring的声明式事务管理 在现代软件开发中,事务处理是非常关键的一部分,特别是在涉及多个数据操作时。Spring框架提供了强大的事务管理能力,可以方便地集成到应用程序中。...

    JdbcTemplate的事务控制.docx

    #### 四、JdbcTemplate与Spring事务控制的结合 当使用`JdbcTemplate`结合Spring框架时,可以采用与原生JDBC事务控制类似的方法,但在Spring环境中进行管理。以下是一个使用Druid数据库连接池的示例代码: ```java ...

    spring 事务传播 demo

    在Java后端开发中,Spring的事务管理机制大大简化了事务控制,使得开发者可以更专注于业务逻辑,而不用关心底层事务的管理。通过声明式事务管理,我们只需在方法上添加@Transactional注解,而无需编写手动的try-...

    Spring事务管理开发必备jar包

    本资源包提供了进行Spring事务管理开发所需的所有关键库,包括框架基础、核心组件、AOP(面向切面编程)支持、日志处理、编译工具以及与数据库交互的相关jar包。下面将对这些知识点进行详细解释: 1. **Spring框架*...

    spring事务案例分析.zip

    本主题将深入探讨“Spring事务案例分析.zip”中的关键知识点,包括Spring事务管理及其在实际项目中的应用。 首先,我们来了解什么是Spring事务管理。在分布式系统或数据库操作中,事务管理是确保数据一致性和完整性...

    Spring事务管理的jar包

    除了基本的事务控制,Spring还提供了丰富的事务属性,如传播行为(PROPAGATION_REQUIRED、PROPAGATION_SUPPORTS等)、隔离级别(ISOLATION_DEFAULT、ISOLATION_READ_UNCOMMITTED等)和事务超时设置,允许开发者根据...

    Spring事务小demo

    这个名为"Spring事务小demo"的项目提供了一个实践示例,帮助开发者了解Spring事务处理的基本概念和用法。 首先,Spring事务管理是Spring框架的核心特性之一,它允许我们以声明式或编程式的方式管理事务。声明式事务...

    spring事务操作试验

    本文将深入探讨在"spring事务操作试验"中涉及的关键知识点,并结合提供的资源进行详细阐述。 首先,Spring事务管理的核心概念是ACID(原子性、一致性、隔离性和持久性),这是所有事务系统的基础。在Spring中,事务...

    Spring中事务的传播属性详解

    这意味着`methodB`的操作不受事务控制。 6. **PROPAGATION_NEVER** `methodB`将以非事务方式执行。如果当前存在事务,那么将抛出异常。这种行为适用于那些不能在事务中执行的操作。 7. **PROPAGATION_NESTED** ...

    Spring 事务简单完整例子

    本文将深入探讨在Spring框架中如何管理事务,以“Spring 事务简单完整例子”为出发点,结合标签“spring,事务,jdbc事务”,我们将详细解释Spring事务管理的原理和实践。 首先,Spring提供了两种事务管理方式:编程...

    声明式事务控制spring+hibernate集成

    在"声明式事务控制,spring2.5+hibernate3集成源码"中,开发者可以学习如何配置Spring的事务管理器,以及如何在Hibernate的SessionFactory和SessionFactoryBuilder上使用Spring的TransactionProxyFactoryBean来创建...

    Spring事务管理失效原因汇总

    标题“Spring事务管理失效原因汇总”指出了本文的核心内容是分析在使用Spring框架进行事务管理时可能遇到的问题及其原因。描述部分进一步说明了事务失效的后果往往不明显,容易在测试环节被忽略,但在生产环境中出现...

    SPRING事务机制DEMO

    通过分析这个文件,我们可以看到如何将AOP和事务管理结合起来,实现对数据库操作的事务控制,以及在特定操作前后执行自定义逻辑。 总结来说,Spring事务机制和AOP是Java开发中的重要工具,它们帮助我们构建可维护、...

    spring学习事务源码

    本文将深入探讨Spring事务管理的源码,理解其背后的实现机制。 首先,Spring事务管理有两种主要模式:编程式事务管理和声明式事务管理。编程式事务管理通过调用`PlatformTransactionManager`接口提供的方法进行显式...

Global site tag (gtag.js) - Google Analytics