ICode9

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

Spring学习总结(十二):Spring中的事务管理

2021-01-20 13:57:20  阅读:188  来源: 互联网

标签:事务管理 事务 Spring 十二 回滚 dataSource 方法 public


        在上一篇的最后,我们引出了问题的产生,接下来看看Spring中是如何解决此类问题的。

一、Spring中事务属性的介绍

       Spring中事务的属性有以下几种:

(1)事务传播行为(propagation)

当事务方法被另一个事务方法调用时,必须指定事务应该如何传播。例如:方法可能继续在现有事务中运行,也可能开启一个新事务,并在自己的事务中运行。Spring定义了七种传播行为,如下表:

传播行为描述
PROPAGATION_REQUIREDrequired表示当前方法必须运行在事务中。如果当前事务存在,方法将会在该事务中运行。否则就开启一个新的事务
PROPAGATION_SUPPORTSsupports表示当前方法不需要事务上下文,但是如果存在当前事务的话,那么该方法会在这个事务中运行。
PROPAGATION_MANDATORYmandatory表示该方法必须在事务中运行,如果当前事务不存在,则抛出一个异常。
PROPAGATION_REQUIRED_NEWrequired_new表示当前方法必须运行在它自己的事务中。一跟新的事务会被启动。如果存在当前事务,在该方法执行期间,原事务被挂起。如果使用JATransactionManager的话,则需要访问TransactionManager
PROPAGATION_NOT_SUPPORTEDnot_supported表示该方法不应该运行在事务中。如果存在当前事务,在该方法执行期间,原事务被挂起。如果使用JATransactionManager的话,则需要访问TransactionManager
PROPAGATION_NEVERnever表示当前方法不应该运行在事务上下文中。如果当前正有一个事务在运行,则抛出异常
PROPAGATION_NESTEDnested表示如果当前已经存在一个事务,那么该方法将会在嵌套事务中运行。嵌套的事务可以独立于当前事务进行单独地提交或回滚。如果当前事务不存在,那么其行为与PROPAGATION_REQUIRED一样

(2)事务隔离级别(isolation)

Spring中的五种事务隔离级别:
DEFAULT:使用后端数据库默认的隔离级别(spring中的的选择项)
READ_UNCOMMITED:允许你读取还未提交的改变了的数据。可能导致脏、幻、不可重复读。
READ_COMMITTED:允许在并发事务已经提交后读取。可防止脏读,但是读和不可重复读仍可发生。
REPEATABLE_READ:对相同字段的多次读取是一致的,除非数据被事务本身改变。可防止脏、不可重复读,但幻读仍可能发生。
SERIALIZABLE:完全服从ACID的隔离级别,确保不发生脏、幻、不可重复读。这在所有的隔离级别中是最慢的,它是典型的通过完全锁定在事务中涉及的数据表来完成的。

(3)超时时间(timeout)

事务需要在一定时间内提交,如果不提交就进行回滚。默认值是-1,设置时间以秒为单位。

(4)是否只读(readOnly)

默认值为false,表示可以查询、修改、删除、添加等操作。读指的是查询操作,写指的是添加修改删除操作。

(5)回滚(rollbackFor)

设置出现哪些异常事务回滚。

(6)不回滚(noRollbackFor)

设置出现哪些异常事务不进行回滚。

二、编程式事务管理

       编程式事务指的是通过编码方式实现事务,即类似于 JDBC 编程实现事务管理。管理使用 TransactionTemplate 或者直接使用底层的 PlatformTransactionManager。对于编程式事务管理,spring 推荐使用 TransactionTemplate。

(1)bean.xml中配置transactionTemplate和事务管理器

    <!--  配置transactionTemplate -->
    <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate">
        <property name="transactionManager" ref="transactionManager"></property>
    </bean>

    <!--  创建事务管理器  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

(2) 在tranferAccount()方法中通过transactionTemplate.execute执行逻辑,通过TransactionCallback接口中的方法后将返回值传递到TransactionTemplate的execute()中。通过调用TransactionStatus 的setRollbackOnly()方法来实现事物回滚。

@Service
public class UserService {
    @Autowired
    private IUserDao userDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void tranferAccount(){
        transactionTemplate.execute(new TransactionCallback<String>() {

            @Override
            public String doInTransaction(TransactionStatus transactionStatus) {
                try{
                    userDao.reduceMoney();
                    int i = Integer.parseInt("123a");
                    userDao.addMoney();
                }catch (Exception e){
                    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动开启事务回滚
                    transactionStatus.setRollbackOnly();
                    return null;
                }
                return null;
            }
        });

    }
}

三、声明式事务管理

       声明式事务管理建立在 AOP 之上的。其本质是对方法前后进行拦截,然后目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。声明式事务最大的优点就是不需要通过编程的方式管理事务,这样就不需要在业务逻辑代码中掺杂事务管理的代码,只需在配置文件中做相关的事务规则声明 (或通过基于 @Transactional 注解的方式),便可以将事务规则应用到业务逻辑中

1、基于XML的声明式事务管理

<!--  创建事务管理器  -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>
    <!-- 编写通知:对事务管理器进行增强(通知),编写切入点和具体执行事务的细节   -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <!--    给切入点方法添加事务详情        -->
            <tx:method name="tranferAccount" propagation="REQUIRED" isolation="READ_COMMITTED"/>
            <tx:method name="*" read-only="false"/>
        </tx:attributes>
    </tx:advice>
    <!--  Aop编写:让Spring自动对目标生成代理,需要使用 AspectJ表达式 -->
    <aop:config>
        <!--    切入点    -->
        <aop:pointcut id="pt" expression="execution(* com.yht.example8.service.UserService.*(..))"/>
        <!--   切面:将切入点和通知整合     -->
        <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
    </aop:config>

2、基于注解的声明式事务管理

(1)在bean.xml中开启事务注解

    <!--  开启事务注解  -->
    <tx:annotation-driven></tx:annotation-driven>

(2)修改UserService类,添加注解@Transactional

@Service
@Transactional
public class UserService {
    @Autowired
    private IUserDao userDao;
    @Autowired
    private TransactionTemplate transactionTemplate;
    public void tranferAccount(){
        userDao.reduceMoney();
        int i = Integer.parseInt("123a");
        userDao.addMoney();
    }
}

说明:完全注解方式实现声明式事务管理,在config下提供一个MyAopConfig类,如下:

@Configuration    //配置类
@ComponentScan("com.yht.example8")      //组件扫描
@EnableAspectJAutoProxy     //开启事务
public class MyAopConfig {
    // @Bean:用于把当前方法的返回值作为bean对象存入spring的ioc容器中

    /**
     * 获取数据库连接池
     * @return
     */
    @Bean
    public DruidDataSource getDruidDataSource(){
        DruidDataSource dataSource = new DruidDataSource();
        dataSource.setDriverClassName("com.mysql.jdbc.Driver");
        dataSource.setUrl("jdbc:mysql://localhost:3306/test");
        dataSource.setUsername("root");
        dataSource.setPassword("root");
        return dataSource;
    }

    /**
     * 获取JdbcTemplate
     * @param dataSource 由IOC容器提供
     * @return
     */
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource){
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //注入dataSource
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }
}

 

标签:事务管理,事务,Spring,十二,回滚,dataSource,方法,public
来源: https://blog.csdn.net/weixin_47382783/article/details/112861374

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

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

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

ICode9版权所有