前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring声明式事务详解

Spring声明式事务详解

作者头像
JavaEdge
发布2022-11-30 15:38:04
4090
发布2022-11-30 15:38:04
举报
文章被收录于专栏:JavaEdge

1 事务管理

  • 提供的统一的API接口支持不同的资源
  • 提供声明式事务管理
  • 方便的与Spring框架集成
  • 多个资源的事务管理、同步

2 事务抽象

2.1 事务管理器 - PlatformTransactionManager

代码语言:javascript
复制
public interface PlatformTransactionManager {
	TransactionStatus getTransaction(TransactionDefinition definition)
throws TransactionException;
	void commit(TransactionStatus status) throws TransactionException;
	void rollback(TransactionStatus status) throws TransactionException;
}	

2.2 事务定义 - TransactionDefinition

代码语言:javascript
复制
public interface TransactionDefinition {
	int getPropagationBehavior();
	int getlsolationLevel();
	String getName();
	int getTimeout();
	boolean isReadOnly();
}

2.3 事务隔离机制

代码语言:javascript
复制
TransactionDefinition.ISOLATION_DEFAULT
TransactionDefinition.ISOLATION_READ_COMMITTED
TransactionDefinition.ISOLATION_READ_UNCOMMITTED
TransactionDefinition.ISOLATION_REPEATABLE_READ
TransactionDefinition.ISOLATION_SERIALIZABLE

2.4 事务传播机制

TransactionDefinition接口定义了如下int 常量:

PROPAGATION_REQUIRED (Default)

支持当前事务; 如果不存在,请创建一个新的。事务定义的默认设置,并且定义了事务同步的作用域

PROPAGATION_SUPPORTS

支持当前事务; 如果不存在,则以非事务方式执行。 对于具有事务同步的事务管理器, PROPAGATION_SUPPORTS与根本没有事务略有不同,因为它定义了同步可能适用的事务范围。 结果,将为整个指定范围共享相同的资源(JDBC Connection ,Hibernate Session等)。 准确的行为取决于事务管理器的实际同步配置! 通常,请谨慎使用PROPAGATION_SUPPORTS ! 特别是,不要依赖PROPAGATION_SUPPORTS范围内的

  • PROPAGATION_REQUIRED
  • PROPAGATION_REQUIRES_NEW (这可能会在运行时导致同步冲突)

如果这种嵌套是不可避免的,请确保正确配置事务管理器(通常切换为“实际事务同步”)

PROPAGATION_MANDATORY

PROPAGATION_REQUIRES_NEW

PROPAGATION_NOT_SUPPORTED

不支持当前事务;而是始终以非事务方式执行。类似于同名的EJB事务属性。 实际的事务中止将无法在所有事务管理器中立即使用。 这尤其适用于org.springframework.transaction.jta.JtaTransactionManager ,它要求javax.transaction.TransactionManager对其可用(在标准Java EE中是特定于服务器的)。 事务同步在PROPAGATION_NOT_SUPPORTED作用域内不可用。 现有同步将被挂起并适时恢复

TransactionDefinition.PROPAGATION_NEVER

不支持当前事务;如果当前事务存在,则抛异常。类似于同名的EJB事务属性。事务同步在PROPAGATION_NEVER作用域内不可用

  • PROPAGATION_NESTEDED
  • REQUIRED 适用于增删改
  • SUPPORTS 适用于查询。

TransactionStatus

Spring提供了PlatformTransactionManager表示事务管理器,所有事务都由它管理。 而事务由TransactionStatus表示。

代码语言:javascript
复制
public interface TransactionStatus extends SavepointManager {
	boolean isNewTransaction();
	boolean hasSavepoint();
	void setRollbackOnly();
	boolean isRollbackOnly();
	boolean isCompleted();
}

如果手写事务代码,使用try…catch如下:

代码语言:javascript
复制
TransactionStatus tx = null;
try {
    // 开启事务:
    tx = txManager.getTransaction(new DefaultTransactionDefinition());
    // 相关JDBC操作:
    jdbcTemplate.update("...");
    jdbcTemplate.update("...");
    // 提交事务:
    txManager.commit(tx);
} catch (RuntimeException e) {
    // 回滚事务:
    txManager.rollback(tx);
    throw e;
}

为啥要抽象出PlatformTransactionManager和TransactionStatus?

JavaEE除了提供JDBC事务,还支持分布式事务JTA(Java Transaction API)。分布式事务是指多个数据源(比如多个数据库,多个消息系统)要在分布式环境下实现事务的时候,应该怎么实现。分布式事务实现起来非常复杂,简单说就是通过一个分布式事务管理器实现两阶段提交,但本身数据库事务就不快,基于数据库事务实现的分布式事务就慢得难以忍受,所以使用率不高。

Spring为了同时支持JDBC和JTA两种事务模型,就抽象出PlatformTransactionManager。 因为我们的代码只需要JDBC事务,因此,在AppConfig中,需要再定义一个PlatformTransactionManager对应的Bean,它的实际类型是DataSourceTransactionManager:

代码语言:javascript
复制
@Configuration
@ComponentScan
@PropertySource("jdbc.properties")
public class AppConfig {
    ...
    @Bean
    PlatformTransactionManager createTxManager(@Autowired DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}

3 代码实战

代码语言:javascript
复制
public OrderService {
	@Autowire PlatformTransactionManager txManager
	void buyTicket(BuyTicketDTO dto) {
		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION REQUIRED);
		TransactionStatus status = txManager.getTransaction(def);
		try {
			//执行业务代码
			txManager.commit(status);
		} catch (Exception e) {
			txManager.rollback(status);
		}
	}	
}	

Transactional标签方式实现1

代码语言:javascript
复制
public OrderService {
	@Transactonal
	void buyTicket(BuyTicketDTO dto) {
	/ save order
	// finish customer pay
	// transfer tickets
	}
}	

Transactional标签方式实现2

代码语言:javascript
复制
public OrderServiceProxy {
	void buyTicket(BuyTicketDTO dto) {
		// get and begin transaction manager from context
		try{
			orderServicelmpl.buyTicket(dto);
			// commit transaction
		} catch (Exceptione) {
			// roolbback transaction
	}
}	
  • 执行原理流程图

PlatformTransactionManager常见实现

  • DataSourceTransactionManager
  • JpaTransactionManager
  • JmsTransactionManager
  • JtaTransactionManager

但使用声明式事务经常遇到问题:

  • 数据库连接耗尽
  • 处理中的问题(比如调用接口超时)
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020-11-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1 事务管理
  • 2 事务抽象
    • 2.1 事务管理器 - PlatformTransactionManager
      • 2.2 事务定义 - TransactionDefinition
        • 2.3 事务隔离机制
          • 2.4 事务传播机制
            • PROPAGATION_REQUIRED (Default)
            • PROPAGATION_SUPPORTS
            • PROPAGATION_MANDATORY
            • PROPAGATION_REQUIRES_NEW
            • PROPAGATION_NOT_SUPPORTED
            • TransactionDefinition.PROPAGATION_NEVER
          • TransactionStatus
            • 为啥要抽象出PlatformTransactionManager和TransactionStatus?
              • Transactional标签方式实现1
          • 3 代码实战
            • PlatformTransactionManager常见实现
            相关产品与服务
            数据库
            云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档