ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Spring事务控制

2021-02-02 16:57:35  阅读:141  来源: 互联网

标签:控制 事务 Spring 事务处理 PROPAGATION 提交 public


代码下载

  • 链接:https://pan.baidu.com/s/1-PpBJQ1-O7Wjg1CfVb_1Mg
  • 提取码:xwxd

Spring事务控制

Spring事务控制介绍

只要是项目,都是基于数据库进行开发的,对于数据库而言,为保证数据的一致性,对事务处理提出了四大基本原则:即原子性、一致性、隔离性、持久性。并发操作同一数据时,通过不同的隔离级别来保证多个用户之间的操作的数据不会相互影响。避免脏读、不可重复的、幻读问题,最后通过事务提交来确保最终所操作数据的。一致性

要想使用Spring事务控制,需要引入相关依赖包:

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.3</version>
</dependency>

Spring对事务的提交也提供了支持,其核心接口:public interface PlatformTransactionManager
该接口提供了事务处理方法:

方法描述
TransactionStatus getTransaction(TransactionDefinition definition)获取当前的事务状态
void commit(TransactionStatus status)提交事务
void rollback(TransactionStatus status)回滚数据

根据该接口提供的方法描述,要想进行事务的提交,我们需要使用TransactionDefinition接口来指定具体的事务传播属性,并通过**getTransaction()**方法获取事务状态,才可以进行事务的提交和回滚操作。

事务的传播属性

事务的传播描述的是,当前所执行的事务处理是否继续沿用到其他方法上。
TransactionDefinition定义了如下7个属性:

属性名称描述
PROPAGATION_MANDATORY支持当前事务,如果当前没有事务运行,则抛出异常
PROPAGATION_NESTED如果当前有事务运行则嵌套在当前事务中运行,如果没有则以PROPAGATION_REQUIRED
PROPAGATION_NEVER以非事务的方式运行,如果当前有事务,则抛出异常
PROPAGATION_NOT_SUPPORTED不执行当前事务,以非事务的方式来运行
PROPAGATION_REQUIRED执行当前事务处理,如果当前没有事务,则创建一个新的事务处理
PROPAGATION_REQUIRES_NEW总是创建一个新的事务来运行,如果当前存在是否,则挂起当前事务
PROPAGATION_SUPPORTS执行当前事务,如果当前没有事务运行则执行非事务处理

范例:spring事务处理,这里使用到的数据层开发组件是Spring提供JdbcTemplate

@ContextConfiguration(locations = {"classpath:applicationContext.xml"})
@RunWith(SpringJUnit4ClassRunner.class)
public class TestJdbcTemplate {

    @Autowired
    private JdbcTemplate jdbcTemplate;

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Test
    public void testInsert() {
        // TransactionDefinition的子类DefaultTransactionDefinition,用于设置具体使用的传播属性
        DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition();
        
        // 设置传播属性
        defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        
        // 设置数据库隔离级别,此处使用默认的隔离级别
        defaultTransactionDefinition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
        
        // 获取事务状态
        TransactionStatus transactionStatus = this.platformTransactionManager.getTransaction(defaultTransactionDefinition);
        try {
            String sql = "INSERT INTO user_info VALUES(?, ?, ?)";
            this.jdbcTemplate.update(sql, null, "谭旭鹏", 20);
            
            // 提交事务
            this.platformTransactionManager.commit(transactionStatus);
        }catch (Exception e){
        	
        	// 回滚事务
            this.platformTransactionManager.rollback(transactionStatus);
        }
    }
}

理解事务传播属性?

在原生的Java开发中,对数据库的交互支持只有JDBC,其提供的Connection接口有如下的事务操作方法:

方法描述
void commit()提交事务
void rollback()回滚事务
void setAutoCommit(boolean autoCommit)设置事务是否自动提交:false取消、true自动提交

在正常的开发中,都是基于分层的模式开发,即将业务与数据分离,而我们一个业务当中可能会去操作多个数据,比如我们要实现一个积分兑换功能,那么该功能会有如下的数据动作:

  • 查询该用户积分是否满足所兑换的商品
  • 扣除用户的积分
  • 为该用户增加所兑换的物品

所以我们的事务处理放在业务层最为合适,当我们成功扣除用户积分时,就在为该用户增加所兑换物品,如果此时发生了错误,则回滚。那这个用户的积分也不会受到影响。如下图:
在这里插入图片描述但是,还有一种业务层调用业务层的情况,如下视频范例:

<iframe allowfullscreen="true" data-mediaembed="csdn" id="cMlFormO-1612255568249" src="https://live.csdn.net/v/embed/150083"></iframe>

jdbc事务演示

可以发现,修改完数据回到增加方法时,发生了错误,在一个业务中,增加没有成功,而修改却成功了。这样最终操作的结果就是错误的。

范例:使用Spring事务控制进行事务处理

<iframe allowfullscreen="true" data-mediaembed="csdn" id="YID4jDfy-1612255593660" src="https://live.csdn.net/v/embed/150195"></iframe>

Spring事务控制演示

使用注解配置Spring事务控制

在实际的开发中,肯定不会像上面的代码一样,手动实例化子类,手动进行事务的提交和回滚操作,我们可以通过注解来配置Spring事务控制,由Spring自动帮助我们完成事务的提交操作。在Spring配置文件中加入如下配置:

开启Spring事务注解:<tx:annotation-driven transaction-manager=“transactionManager”/>
在这里插入图片描述使用 @Transactional 设置事务传播属性

// 业务层接口操作标准
@Service
public interface IUserInfoService {
	@Transactional(propagation = Propagation.REQUIRED)
	int addUserInfo();
}
// 业务层实现子类
@Service
public class UserInfoServiceImpl implements IUserInfoService {
	@Autowired
	private IUserInfoDAO userInfoDAO;

	@Override
	public int addUserInfo() {
        return this.userInfoDAO.doCreateUserInfo();
	}
}

// 数据层接口
public interface IUserInfoDAO {
	int doCreateUserInfo();
}

// 数据层实现子类
@Repository
public class UserInfoDAOImpl implements IUserInfoDAO{
	@Autowired
	private JdbcTemplate jdbcTemplate;
 
	@Override
	public int doCreateUserInfo() {
        String sql = "INSERT INTO user_info VALUES(?, ?, ?)";
        return this.jdbcTemplate.update(sql, null, "老铁", 18);
	}
}

使用AOP代理事务处理

要想使用aop动态代理帮助我们完成事务自动处理,除了需要引入事务依赖外,还需要引入aop依赖

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-tx</artifactId>
    <version>5.3.3</version>
</dependency>

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aop</artifactId>
    <version>5.3.3</version>
</dependency>
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-aspects</artifactId>
    <version>5.3.3</version>
</dependency>

在spring配置文件中,配置要代理事务处理的方法

<!-- 事务处理 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource" />
</bean>
<!-- 
    配置事务:
        是add、edit、delete开头的方法,都是用REQUIRED事务属性
        是get开头的方法,则以只读运行
-->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
    <tx:attributes>
        <tx:method name="add*" isolation="DEFAULT" propagation="REQUIRED"/>
        <tx:method name="edit*" isolation="DEFAULT" propagation="REQUIRED"/>
        <tx:method name="delete*" isolation="DEFAULT" propagation="REQUIRED"/>
        <tx:method name="get*" isolation="DEFAULT" propagation="REQUIRED" read-only="true"/>
    </tx:attributes>
</tx:advice>

<!-- 通过aop配置代理 -->
<aop:config>
    <aop:pointcut expression="execution(public * com.txp.service..*.*(..))" id="txPointcut"/>
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
</aop:config>

标签:控制,事务,Spring,事务处理,PROPAGATION,提交,public
来源: https://blog.csdn.net/qq_37291829/article/details/113564918

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有