ICode9

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

Spring5# 事务管理

2021-01-25 13:04:49  阅读:153  来源: 互联网

标签:事务管理 事务 money dataSource public 运行 Spring5


目录

Spring 事务管理概述

事务是数据库操作的最基本单元,是逻辑上的一组操作。
典型场景:银行转账。

具有四个特性:
1)原子性
2)一致性
3)隔离性
4)持久性

事务一般添加到 service 层。

在 Spring 中有两种事务管理操作:
1. 编程式(一般不使用)
2. 声明式
	2.1 基于 XML配置文件 方式实现(一般不使用)
	2.2 基于注解方式实现
	
声明式事务管理底层原理是 AOP。

Spring 事务管理的 API
1. Spring 提供事务管理器接口,这个接口根据不同的框架提供不同的实现类。

编程式事务管理

//编程式事务管理操作
//Dao
@Override
public void reduceMoney(String id, int money) {
    String sql = "update t_account set money=money-? where id=?";
    Object[] args = {money, id};
    jdbcTemplate.update(sql, args);
}

@Override
public void addMoney(String id, int money) {
    String sql = "update t_account set money=money+? where id=?";
    Object[] args = {money, id};
    jdbcTemplate.update(sql, args);
}

//Service
@Service
public class UserService {
    @Autowired
    private UserDao userDao;

    public void dispote (String outId, String inId, int money) {
        //事务管理操作步骤
        try {
            //开启事务
            //业务操作
            userDao.reduceMoney("1", money);
            //模拟异常
            //int i = 10/0;
            userDao.addMoney("2", money);
            //没有异常,提交事务
        } catch (Exception e) {
            //出现异常,回滚事务
        }

    }
}

声明式事务管理

基于注解方式
步骤: 
1. 在 Spring 配置文件中创建事务管理器。
2. 在 Spring 配置文件中开启事务注解。
	2.1 引入名称空间 tx。
	2.2 开启事务注解。
3. 在 Service 类上面或在 Service 类中的特定方法上面添加事务注解 @Transactional。
	# 在类上面添加,则类中所有方法都添加事务。
<!-- 配置事务管理器(框架不同,实现类不同) -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<!-- 注入数据源 -->
	<property name="dataSource" ref="dataSource"></property>
</bean>


<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>
//声明式事务管理,基于注解实现
@Service
@Transactional
public class UserService {
    @Autowired
    private UserDao userDao;

    public void dispote (String outId, String inId, int money) {
        //不需要再用 try catch 处理。如果用了,则事务不会生效
        userDao.reduceMoney("1", money);
        //模拟异常
        int i = 10/0;
        userDao.addMoney("2", money);
    }
}
声明式事务管理的参数配置
@Transactional()
1. propagation:事务传播行为,MySQL 默认是 REQUIRED
2. isolation:事务隔离级别
3. timeout:超时
4. readOnly:是否只读
5. rollbackFor:回滚
6. noRollbackFor:不回滚
事务传播行为
指多事务方法之间直接进行调用,这个过程事务是如何进行管理的。
	#事务方法:修改了数据库表数据的方法,如增删改。

Spring 框架有 7 种事务传播行为:
* 1)REQUIRED:如果有事务在运行,当前方法就在这个事务内运行,否则,就启动一个新的事务,并在自己的事务内运行。
* 2)REQUIRED_NEW:当前的方法必须启动新事务,并在它自己的事务内运行,如果有事务正在运行,应该将它挂起。
3)SUPPORTS:如果有事务在运行,当前方法就在这个事务内运行,否则,它可以不在事务内运行。
4)NOT_SUPPORTED:当前的方法不应该运行在事务中,如果有运行的事务,将它挂起。
5)MANDATROY:当前的方法必须运行在事务内部,如果没有正在运行的事务,就抛出异常。
6)NEVER:当前的事务不应该在事务中运行,如果有运行的事务,就抛出异常。
7)NESTED:如果有事务在运行,当前的方法就应该在事务的嵌套事务内运行,否则,就启动一个新的事务,并在它自己的事务内运行。
事务隔离级别
事务隔离性:多事务操作之间不会产生影响。
如果不考虑隔离性,会产生很多问题:
	#读问题:脏读、不可重复读、虚(幻)读
	1. 脏读:一个未提交事务读取到另一个未提交事务的数据。
	2. 不可重复读:一个未提交事务读取到另一个提交事务修改后的数据。
	3. 虚读:一个未提交事务读取到另一个提交事务添加的数据。

事务的四种隔离级别:MySQL 默认是 REPEATABLE READ
1)READ UNCOMMITTED:读未提交。
	#有脏读、有不可重复读、有幻读
2)READ COMMITTED:读已提交。
	#无脏读、有不可重复读、有幻读
3)REPEATABLE READ:可重复读。
	#无脏读、无不可重复读、有幻读
4)SERIALIZABLE:串行化。
	#无脏读、无不可重复读、无幻读
其他参数
timeout:事务需要在规定的时间内提交,否则回滚。默认值是 -1,不超时。单位为秒。
readOnly:是否只读,默认值是 false
rollbackFor:设置出现哪些异常就进行事务回滚。
noRollbackFor:设置出现哪些异常就不进行事务回滚。
基于 XML 方式
步骤:
1. 配置事务
2. 配置通知
3. 配置切入点和切面
<!-- 配置事务 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
	<!-- 注入数据源 -->
	<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置通知 -->
<tx:advice id="txAdvice">
    <!-- 配置事务参数 -->
    <tx:attributes>
        <!-- 指定规则,并在符合规则的方法上面添加事务 -->
        <tx:method name="dispote" propagation="REQUIRED"/>
        <!-- <tx:method name="dis*" propagation="REQUIRED"/> -->
    </tx:attributes>
</tx:advice>

<!-- 配置切入点和切面 -->
<aop:config>
    <!-- 配置切入点 -->
    <aop:pointcut id="pt" expression="execution(* work.service.UserService.*(..))"/>
    <!-- 配置切面 -->
    <aop:advisor advice-ref="txAdvice" pointcut-ref="pt"></aop:advisor>
</aop:config>
完全注解方式
//TxConfig
@Configuration //定义配置类
@ComponentScan(basePackages = {"work"}) //开启组件扫描
@EnableTransactionManagement //开启事务
public class TxConfig {

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

    //创建 JdbcTemplate 对象
    @Bean
    public JdbcTemplate getJdbcTemplate(DataSource dataSource) {
        //到 IOC 容器中根据类型找到 dataSource
        JdbcTemplate jdbcTemplate = new JdbcTemplate();
        //注入 dataSource 到 jdbcTemplate
        jdbcTemplate.setDataSource(dataSource);
        return jdbcTemplate;
    }

    //创建事务管理器
    @Bean
    public DataSourceTransactionManager getDataSourceTransactionManager(DataSource dataSource) {
        DataSourceTransactionManager dataSourceTransactionManager
                = new DataSourceTransactionManager();
        dataSourceTransactionManager.setDataSource(dataSource);
        return dataSourceTransactionManager;
    }
}

//test
@Test
public void testDispote() {
    ApplicationContext context
        = new AnnotationConfigApplicationContext(TxConfig.class);
    UserService userService = context.getBean("userService", UserService.class);
    userService.dispote("1", "2", 100);
}
<!-- 被配置类取代的配置文件 -->
<context:component-scan base-package="jdbctemplate, work"></context:component-scan>

<bean id="dataSource" class="com.alibaba.druid.pool.DruidDataSource" destroy-method="close">
    <property name="url" value="jdbc:mysql://localhost:3306/user_db"></property>
    <property name="username" value="root"></property>
    <property name="password" value="root"></property>
    <property name="driverClassName" value="com.mysql.jdbc.Driver"></property>
</bean>

<!-- 配置 JdbcTemplate 对象 -->
<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <!-- 注入 dataSource -->
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <!-- 注入数据源 -->
    <property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 开启事务注解 -->
<tx:annotation-driven transaction-manager="transactionManager"></tx:annotation-driven>

标签:事务管理,事务,money,dataSource,public,运行,Spring5
来源: https://www.cnblogs.com/zhugaoxiang/p/14324612.html

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

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

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

ICode9版权所有