mysql 事务-demo

mysql 事务

基本ssm框架

为什么要事务

比如转账A转给B 1000块,然后正常要两个update来做加减,但问题来了,万一一个update成功,一个失败,怎么办

先总结

使用事务 ,方法里的多个crud, 一个失败全部失败,全部成功才能成功

一、直接上demo

当一个方法,需要使用到多次sql的 insert 或者update 或者delete时,
正常的demo会用转账来举例,但是我觉得是太复杂了
我随便举个比如在修改密码的时候,要用到两次update

1.接口类

/**
 * <p>
 *  服务类
 * </p>
 *
 * @author zyl
 * @since 2020-09-23
 */
public interface CwdUserService extends IService<CwdUser> {
	//通过id获取用户对象 
     CwdUser getById(String userid); 
     // 更新密码
    int updatePwd(CwdUser user);
 
}

2.接口实现
修改密码方法的实现,这里忽略controll 的参数处理,调用这个方法的时候,user的密码已经是新密码了,
业务简单

    @Override
    public int updatePwd(CwdUser user) {
      	 mapper.updatePwd(user);
 		return 0;
    }

3.dao对应的mapper


    <update id="updatePwd" parameterType="com.resab.sys.model.CwdUser">
        update cwd_user
        <set>
            <if test="password != null">password=#{password},</if>
            <if test="status != null">status=#{status},</if>
        </set>
        where userid=#{userid}
    </update>

说人话就是

update toilet.cwd_user SET password='新密码', status='用户的状字段长度为8' where userid='fb65bd444cc74e09a6da5bb5e312de91'

二、没有事务

1.加入多次update

第二次update会失败

     @Override
    public int updatePwd(CwdUser user) {


        logoutPwd(user, 1+"更新密码前");
        //更新了密码
        mapper.updatePwd(user);

        // 假设有某些时候,需要顺便改一下别的东西
        // 假设这两个步骤不方便一步到位
        // 分开执行

            user.setStatus("用户的状字段长度为8,过长将会更新失败");
            user.setModifyTime(new Date());
            logoutPwd(user, 2+"更新密码后");
            //更新别的东西
            mapper.updatePwd(user);
        logoutPwd(user, 3+"报错后");
        

        return 0;
    }

    public void logoutPwd(CwdUser user, String i) {
        System.out.println(i + ".现在在数据库里的密码:" + mapper.getById("fb65bd444cc74e09a6da5bb5e312de91").getPassword() + "\n" +
                " ----要更新的新密码:" + user.getPassword());
    }


2.日志打印结果
可以发现 密码更新成功了,虽然密码更新成功了,但是状态没更新成功,这样的代码是有bug的,在转账业务 的时候 ,就会出现A的钱转了,但是B没收到
所以就要有个事务来控制一下

1.现在在数据库里的密码:25f43  ----要更新的新密码:114663
2.现在在数据库里的密码:114663  ----要更新的新密码:114663
3.现在在数据库里的密码:114663  ----要更新的新密码:114663

3.但是控制台报错了
debbug跟踪的时候 ,第二次update报错了
在这里插入图片描述

加入事务

//加这个注解 
    @Transactional
    @Override
    public int updatePwd(CwdUser user) {
			//...同上...
    }

不用猜也知道结果怎么以样了,就是密码没改成功
懒得写了


总结

使用事务 ,方法里多个crud, 一个失败全部失败,全部成功才能成功

注意事项

  • 在需要事务管理的地方加@Transactional 注解。

  • 注解位置:@Transactional 注解可以被应用于接口定义和接口方法、类定义和类的 public 方法上。

  • @Transactional 注解只能应用到 public 可见度的方法上。 如果你在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不会报错, 但是这个被注解的方法将不会展示已配置的事务设置。

  • 只用于public:注意仅仅 @Transactional 注解的出现不足于开启事务行为,它仅仅 是一种元数据。必须在配置文件中使用配置元素,才真正开启了事务行为。

  • 继承问题:Spring团队建议在具体的类(或类的方法)上使用 @Transactional 注解,而不要使用在类所要实现的任何接口上。在接口上使用 @Transactional 注解,只能当你设置了基于接口的代理时它才生效。

  • 因为注解是 不能继承 的,这就意味着如果正在使用基于类的代理时,那么事务的设置将不能被基于类的代理所识别,而且对象也将不会被事务代理所包装。

  • 调用其他事务方法无效:@Transactional 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。

参考链接 : Spring中@Transactional事务回滚(含实例详细讲解,附源码)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的SpringBoot分布式事务的示例代码: 1. 首先,需要在pom.xml文件中添加以下依赖项: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jta-atomikos</artifactId> </dependency> ``` 2. 然后,在application.yml文件中配置Atomikos事务管理器: ``` spring: jta: atomikos: datasource: xa-data-source-class-name: com.mysql.cj.jdbc.MysqlXADataSource unique-resource-name: ds1 xa-properties: user: root password: root url: jdbc:mysql://localhost:3306/demo?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8 min-pool-size: 5 max-pool-size: 20 test-query: SELECT 1 log-dir: tx-logs max-actives: 50 ``` 3. 接下来,需要编写两个服务(A和B),并使用Atomikos事务管理器来跨服务进行事务控制。 服务A: ``` @Service public class ServiceA { @Autowired private ServiceB serviceB; @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void doSomething() { jdbcTemplate.update("INSERT INTO t_demo(name) VALUES('aaa')"); serviceB.doSomethingElse(); } } ``` 服务B: ``` @Service public class ServiceB { @Autowired private JdbcTemplate jdbcTemplate; @Transactional public void doSomethingElse() { jdbcTemplate.update("INSERT INTO t_demo(name) VALUES('bbb')"); } } ``` 在这个示例中,服务A中的doSomething()方法和服务B中的doSomethingElse()方法都被@Transactional注解标记。这意味着它们在同一个事务中运行,而且如果有任何一个方法失败,整个事务将回滚。 4. 最后,将两个服务作为微服务部署到不同的服务器上(或者使用不同的端口),并使用Spring Cloud或其他工具来使它们协作。 这就是一个简单的SpringBoot分布式事务的示例。当然,实际应用中可能会有更复杂的场景和需求,需要更多的配置和代码来支持。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值