Spring事务管理

Spring框架为事务管理提供了一致的抽象,可以带来以下好处:

  • Java Transaction API(JTA),JDBC,Hibernate,Java Persistence API(JPA)和Java数据对象(JDO)等不同的事务API之间的一致的编程模型
  • 支持声明事务管理
  • 编程式事务管理的API使用简单
  • 与Spring的数据访问抽象集成

1、Spring一致的编程模型

传统上,Java EE开发人员有两种交易管理选择:全局或本地交易,两者都有明显的局限性。

  • 全局事务
    JTA、EJB

优点:可以多资源使用
缺点:JTA API笨重、通过JNDI获取资源。

  • 本地事务
    本地事务是资源专用,比如:JDBC连接。

优点:简单易用。
缺点:不能多资源使用。

1.1、理解Spring事务抽象

Spring事务抽象最重要是事务策略概念,事务策略由org.springframework.transaction.PlatformTransactionManager定义:

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(
            TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

TransactionStatus表示一个新的事务或者当前调用堆栈中存在匹配事务,和执行线程相关联。TransactionStatus实例需要依赖一个
TransactionDefinition实例参数,TransactionDefinition接口定义如下:

public interface TransactionDefinition {

    // 事务传播
    int getPropagationBehavior();

    // 事务隔离级别
    int getIsolationLevel();

    // 事务超时事务
    int getTimeout();

    boolean isReadOnly();

    String getName();

}

TransactionStatus接口定义:

public interface TransactionStatus extends SavepointManager, Flushable {

    boolean isNewTransaction();

    boolean hasSavepoint();

    void setRollbackOnly();

    boolean isRollbackOnly();

    void flush();

    boolean isCompleted();

}

1.2、理解声明式事务

关于Spring Framework的声明式事务支持的最重要的概念是通过AOP代理启用此支持,并且事务性建议由元数据驱动(目前基于XML或基于注释的),AOP与事务元数据的组合产生一个AOP代理,它使用TransactionInterceptor与适当的PlatformTransactionManager实现结合来驱动方法调用的事务。

事务调用过程如下:

事务调用过程

1.2.1、声明式事务示例

  • 基于XML方式

    (1)创建对应数据库DO

        public class User {
    
        private Integer id;
    
        private String name;
        
        private Integer age;
    
        private Integer sex;
    
        public User(Integer id, String name, Integer age, Integer sex) {
            this.id = id;
            this.name = name;
            this.age = age;
            this.sex = sex;
        }
    
        public Integer getId() {
            return id;
        }
    
        public void setId(Integer id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    
        public Integer getSex() {
            return sex;
        }
    
        public void setSex(Integer sex) {
            this.sex = sex;
        }
    }
    

    (2)、创建表与实体间映射

    public class UserRowMapper implements RowMapper<User>{
    
            public User mapRow(ResultSet resultSet, int i) throws SQLException {
    
                User person = new User(
                            resultSet.getInt("id"),
                            resultSet.getString("name"),
                            resultSet.getInt("age"),
                            resultSet.getInt("sex"));
                return person;
            }
        } 
    
    

    (3)、创建UserService接口

    public interface UserService {
    
                void save(User user);
    }
    

    (4)、创建UserService接口实现类

    public class UserServiceImpl implements UserService {
    
        private final static Logger logger = LoggerFactory.getLogger(UserServiceImpl.class);
    
        @Resource
        private JdbcTemplate jdbcTemplate;
    
        @Override
        public void save(User user) {
    
            jdbcTemplate.update("INSERT INTO user(name,age,sex) VALUES (?,?,?)",
                    new Object[]{user.getName(), user.getAge(), user.getSex()},
                    new int[]{Types.VARCHAR, Types.INTEGER, Types.VARCHAR});
        }
    }
    

    (5)、创建Spring配置文件

        <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
            <property name="driverClass" value="com.mysql.jdbc.Driver"/>
            <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test"/>
            <property name="user" value="root"/>
            <property name="password" value="root"/>
        </bean>
    
        <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>
    
        <tx:advice id="txAdvice" transaction-manager="txManager">
            <!-- the transactional semantics... -->
            <tx:attributes>
                <!-- all methods starting with 'get' are read-only -->
                <tx:method name="get*" read-only="true"/>
                <!-- other methods use the default transaction settings (see below) -->
                <tx:method name="*"/>
            </tx:attributes>
        </tx:advice>
    
    
        <aop:config>
            <aop:pointcut id="serviceOperation"
                        expression="execution(* com.codersm.study.spring.tx.service.UserService.*(..))"/>
            <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceOperation"/>
        </aop:config>
    
        <bean id="userService" class="com.codersm.study.spring.tx.service.impl.UserServiceImpl"/>
    
  • 基于注解方式

1.3、事务传播

1.4、其他

1.4.1、Using @Transactional with AspectJ

It is also possible to use the Spring Framework’s @Transactional support outside of a Spring container by means of an AspectJ aspect.

1.4.2、事务绑定事件

1.5 源码分析

<<tx:advice>>标签 = org.springframework.transaction.interceptor.TransactionInterceptor

image.png
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 200,176评论 5 469
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 84,190评论 2 377
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 147,232评论 0 332
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,953评论 1 272
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,879评论 5 360
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,177评论 1 277
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,626评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,295评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,436评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,365评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,414评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,096评论 3 315
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,685评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,771评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,987评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,438评论 2 346
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,032评论 2 341

推荐阅读更多精彩内容

  • 对大多数Java开发者来说,Spring事务管理是Spring应用中最常用的功能,使用也比较简单。本文主要从三个方...
    sherlockyb阅读 3,186评论 0 18
  • 事务是一组操作的原子执行,其中任何一笔操作失败将导致全部操作撤销。 什么是事务? 如上所言,事务遵循ACID原则,...
    点融黑帮阅读 7,790评论 3 36
  • 这部分的参考文档涉及数据访问和数据访问层和业务或服务层之间的交互。 Spring的综合事务管理支持覆盖很多细节,然...
    竹天亮阅读 1,028评论 0 0
  • 一、spring事务介绍 spring事务优点 对不同的api进行统一编程模型,如JTA,JDBC,Hiberna...
    青芒v5阅读 7,770评论 2 22
  • spring支持编程式事务管理和声明式事务管理两种方式。 编程式事务管理使用TransactionTemplate...
    熊熊要更努力阅读 244评论 0 0