zoukankan      html  css  js  c++  java
  • Spring-事务

    Spring 的事务管理是基于 AOP 实现的,而 AOP 是以方法为单位的。Spring 的事务属性分别为传播行为、隔离级别、只读和超时属性,这些属性提供了事务应用的方法和描述策略。

     Java EE 开发经常采用的分层模式中,Spring 的事务处理位于业务逻辑层,它提供了针对事务的解决方案。

    在 Spring 解压包的 libs 目录中,包含一个名称为 spring-tx-3.2.13.RELEASE.jar 的文件,该文件是 Spring 提供的用于事务管理的 JAR 包,其中包括事务管理的三个核心接口:PlatformTransactionManager、TransactionDefinition 和 TransactionStatus。

    将该 JAR 包的后缀名 jar 改成 zip 的形式后,解压压缩包,进入解压文件夹中的 orgspringframework ransaction 目录后,该目录中的文件如图 1 所示。

    事务管理核心接口
    图 1  事务管理核心接口


    在图 1 中,方框所标注的三个文件就是本节将要讲解的核心接口。这三个核心接口的作用及其提供的方法如下。

    1. PlatformTransactionManager

    PlatformTransactionManager 接口是 Spring 提供的平台事务管理器,用于管理事务。该接口中提供了三个事务操作方法,具体如下。

    • TransactionStatus getTransaction(TransactionDefinition definition):用于获取事务状态信息。
    • void commit(TransactionStatus status):用于提交事务。
    • void rollback(TransactionStatus status):用于回滚事务。


    在项目中,Spring 将 xml 中配置的事务详细信息封装到对象 TransactionDefinition 中,然后通过事务管理器的 getTransaction() 方法获得事务的状态(TransactionStatus),并对事务进行下一步的操作。

    2. TransactionDefinition

    TransactionDefinition 接口是事务定义(描述)的对象,它提供了事务相关信息获取的方法,其中包括五个操作,具体如下。

    • String getName():获取事务对象名称。
    • int getIsolationLevel():获取事务的隔离级别。
    • int getPropagationBehavior():获取事务的传播行为。
    • int getTimeout():获取事务的超时时间。
    • boolean isReadOnly():获取事务是否只读。


    在上述五个方法的描述中,事务的传播行为是指在同一个方法中,不同操作前后所使用的事务。传播行为的种类如表 1 所示。

    表 1 传播行为的种类
    属性名称描  述
    PROPAGATION_REQUIRED required 支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将创建新事务
    PROPAGATION_SUPPORTS supports 支持当前事务。如果 A 方法已经在事务中,则 B 事务将直接使用。否则将以非事务状态执行
    PROPAGATION_MANDATORY mandatory 支持当前事务。如果 A 方法没有事务,则抛出异常
    PROPAGATION_REQUIRES_NEW requires_new 将创建新的事务,如果 A 方法已经在事务中,则将 A 事务挂起
    PROPAGATION_NOT_SUPPORTED not_supported 不支持当前事务,总是以非事务状态执行。如果 A 方法已经在事务中,则将其挂起
    PROPAGATION_NEVER never 不支持当前事务,如果 A 方法在事务中,则抛出异常
    PROPAGATION.NESTED nested 嵌套事务,底层将使用 Savepoint 形成嵌套事务


    在事务管理过程中,传播行为可以控制是否需要创建事务以及如何创建事务。

    通常情况下,数据的查询不会改变原数据,所以不需要进行事务管理,而对于数据的增加、修改和删除等操作,必须进行事务管理。如果没有指定事务的传播行为,则 Spring3 默认的传播行为是 required。

    3. TransactionStatus

    TransactionStatus 接口是事务的状态,它描述了某一时间点上事务的状态信息。其中包含六个操作,具体如表 2 所示。

    表 2  事务的操作
    名称说明
    void flush() 刷新事务
    boolean hasSavepoint() 获取是否存在保存点
    boolean isCompleted() 获取事务是否完成
    boolean isNewTransaction() 获取是否是新事务
    boolean isRollbackOnly() 获取是否回滚
    void setRollbackOnly() 设置事务回滚

    1.Dao层

    public interface AccountDao {
        // 汇款
        public int out(String cname, int pid);
        // 收款
        public int in(String cname, int pid);
    }

    2.Dao实现类

    @Repository
    public class AccountDaoImpl implements AccountDao {
        @Resource
        private JdbcTemplate jdbcTemplate;
        @Override
        public int out(String cname, int pid) {
            int update = jdbcTemplate.update("update city set pid=pid-? where cid=?", pid,cname);
            return update;
        }
    
        @Override
        public int in(String cname, int pid) {
            int update = jdbcTemplate.update("update city set pid=pid+? where cid=?", pid,cname);
            return update;
        }
    }

    3.entity实体

    public class City implements Serializable {
        private Integer cid;
        private String cname;
        private Integer pid;
    
        public Integer getCid() {
            return cid;
        }
    
        public void setCid(Integer cid) {
            this.cid = cid;
        }
    
        public String getCname() {
            return cname;
        }
    
        public void setCname(String cname) {
            this.cname = cname;
        }
    
        public Integer getPid() {
            return pid;
        }
    
        public void setPid(Integer pid) {
            this.pid = pid;
        }
    }

    4.service层

    public interface AccountService {
        //转账
        public int transfet(String outUser, String inUser, Integer money);
    }

    5.service实现类

    //@Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false)
    @Service("accountService")
    public class AccountServiceImpl implements AccountService {
        @Resource
        private AccountDao accountDao;
        public void setAccountDao(AccountDao accountDao) {
            this.accountDao = accountDao;
        }
        @Override
        public int transfet(String outUser, String inUser, Integer money) {
            int out = accountDao.out(outUser, money);
            int in = accountDao.in(inUser, money);
            return out+in;
        }
    }

    6.c3p0-db.properties

    jdbc.driverClass =com.mysql.jdbc.Driver
    jdbc.jdbcUrl = jdbc:mysql://localhost:3306/test?serverTimezone=UTC 
    jdbc.user = root
    jdbc.password = root

    7.applicationContext.xml,讲述了三种实现方法,希望对你有些帮助,谢谢

    <?xml version="1.0" encoding="UTF-8"?>
    <!--根节点是我们的beans节点-->
    <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"
           xmlns:aop="http://www.springframework.org/schema/aop"
           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.xsd
                http://www.springframework.org/schema/tx
                http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
                http://www.springframework.org/schema/aop
                http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">
        <!--扫描包-->
        <context:component-scan base-package="cn.spring"/>
        <!--加载properties文件-->
        <context:property-placeholder location="classpath:c3p0-db.properties"/>
        <!--配置数据源。读取properties文件信息-->
        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="${jdbc.driverClass}" />
            <property name="jdbcUrl" value="${jdbc.jdbcUrl}" />
            <property name="user" value="${jdbc.user}" />
            <property name="password" value="${jdbc.password}" />
        </bean>
        <!-- 配置dao -->
        <bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <!-- 事务管理器,依赖于数据源 -->
        <bean id="txManager"
              class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
            <property name="dataSource" ref="dataSource" />
        </bean>
        <!--第一种:事务代理工厂Bean-->
        <bean id="transactionProxyFactoryBean" class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
            <!--事务管理器-->
            <property name="transactionManager" ref="txManager"></property>
            <!--目标对象-->
            <property name="target" ref="accountService"></property>
            <!--设置方法-->
            <property name="transactionAttributes">
                <props>
                    <!--方法对应的隔离级别和传播行为-->
                    <prop key="transfer">PROPAGATION_REQUIRED,ISOLATION_DEFAULT</prop>
                </props>
            </property>
        </bean>
    
        <!--第二种:注册事务管理驱动 -->
       <!-- <tx:annotation-driven transaction-manager="txManager"/>-->
    
    
    
        <!--第三种:-->
        <!-- 编写通知:对事务进行增强(通知),需要编写切入点和具体执行事务的细节 -->
       <!-- <tx:advice id="txAdvice" transaction-manager="txManager">
            <tx:attributes>
                &lt;!&ndash; 给切入点方法添加事务详情,name表示方法名称,*表示任意方法名称,propagation用于设置传播行为,read-only表示隔离级别,是否只读 &ndash;&gt;
                <tx:method name="find*" propagation="SUPPORTS"
                           rollback-for="Exception" />
                <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT"
                           read-only="false" />
            </tx:attributes>
        </tx:advice>
        &lt;!&ndash; aop编写,让Spring自动对目标生成代理,需要使用AspectJ的表达式 &ndash;&gt;
        <aop:config>
            &lt;!&ndash; 切入点 &ndash;&gt;
            <aop:pointcut expression="execution(* cn.spring.service.*.*(..))"
                          id="txPointCut" />
            &lt;!&ndash; 切面:将切入点与通知整合 &ndash;&gt;
            <aop:advisor pointcut-ref="txPointCut" advice-ref="txAdvice" />
        </aop:config>-->
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    </beans>
  • 相关阅读:
    win7承载网络状态不可用,无线网卡驱动更新后也仍然不可用。
    oracle中读写blob字段的问题
    The import javax.servlet cannot be resolved
    关于BLOB数据类型插入ORACLE数据库的操作
    Android Spinner自动弹出列表,设置title
    java.lang.LinkageError: loader constraint violation: when resolving interface... 异常解决
    Java获取网络时间
    android 改变CheckBox和后面文字的间距
    大白话系列之C#委托与事件讲解(序言)
    大白话系列之C#委托与事件讲解(一)
  • 原文地址:https://www.cnblogs.com/lowerma/p/11793998.html
Copyright © 2011-2022 走看看