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 的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个方法调用另一个方法有事务的方法,事务是不会起作用的。