事务相关概念
事务(transaction):最小的不可再分的工作单元;通常一个事务对应一个完整的业务(例如银行账户转账业务,该业务就是一个最小的工作单元)
事务的基本要素(ACID)
1.原子性
2.一致性
3.隔离性
4.持久性
具体见: 事务相关概念_梁云亮的博客-优快云博客
还有事务的并发问题、相关术语、锁等问题这篇文章都有解释
若依框架中对于事务的应用
参考内容:若依-Ruo Yi(分离版学习笔记)_秋子渊的博客-优快云博客_若依学习笔记
新建的Spring Boot项目中,一般都会引用spring-boot-starter或者spring-boot-starter-web,而这两个起步依赖中都已经包含了对于spring-boot-starter-jdbc或spring-boot-starter-data-jpa的依赖。 当我们使用了这两个依赖的时候,框架会自动默认分别注入DataSourceTransactionManager或JpaTransactionManager。 所以我们不需要任何额外配置就可以用@Transactional注解进行事务的使用。
提示
@Transactional注解只能应用到public可见度的方法上,可以被应用于接口定义和接口方法,方法会覆盖类上面声明的事务。
例如用户新增需要插入用户表、用户与岗位关联表、用户与角色关联表,如果插入成功,那么一起成功,如果中间有一条出现异常,那么回滚之前的所有操作, 这样可以防止出现脏数据,就可以使用事务让它实现回退。
做法非常简单,我们只需要在方法或类添加@Transactional注解即可。
@Transactional
public int insertUser(User user)
{
// 新增用户信息
int rows = userMapper.insertUser(user);
// 新增用户岗位关联
insertUserPost(user);
// 新增用户与角色管理
insertUserRole(user);
return rows;
}
昨天阿松问了我个问题,都是要写进数据库的日志,为什么添加角色这种业务逻辑上用到了事务,但是登录这个事没有用事务。
然后我俩就这个问题讨论了半天,研究了半天,最后得出结论:
添加角色啥的业务逻辑需要进行判断,提交的各种数据符合标准才能写入数据库。但是登录这种操作不管成功与否都需要将日志写入数据库,成功了写登录成功,登录失败写登录失败,所以不需要验证是否要写入数据库。
登录相关业务逻辑代码:
/**
* 登录验证
*
* @param username 用户名
* @param password 密码
* @param code 验证码
* @param uuid 唯一标识
* @return 结果
*/
public String login(String username, String password, String code, String uuid)
{
boolean captchaEnabled = configService.selectCaptchaEnabled();
// 验证码开关
if (captchaEnabled)
{
validateCaptcha(username, code, uuid);
}
// 用户验证
Authentication authentication = null;
try
{
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(username, password);
AuthenticationContextHolder.setContext(authenticationToken);
// 该方法会去调用UserDetailsServiceImpl.loadUserByUsername
authentication = authenticationManager.authenticate(authenticationToken);
}
catch (Exception e)
{
if (e instanceof BadCredentialsException)
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, MessageUtils.message("user.password.not.match")));
throw new UserPasswordNotMatchException();
}
else
{
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_FAIL, e.getMessage()));
throw new ServiceException(e.getMessage());
}
}
finally
{
AuthenticationContextHolder.clearContext();
}
AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success")));
LoginUser loginUser = (LoginUser) authentication.getPrincipal();
recordLoginInfo(loginUser.getUserId());
// 生成token
return tokenService.createToken(loginUser);
}
可以看出这玩意儿对于失败的登录请求也是直接记录日志并且抛出异常。
但是创建角色等等业务逻辑就没这么写:
/**
* 新增保存用户信息
*
* @param user 用户信息
* @return 结果
*/
@Override
@Transactional
public int insertUser(SysUser user)
{
// 新增用户信息
int rows = userMapper.insertUser(user);
// 新增用户岗位关联
insertUserPost(user);
// 新增用户与角色管理
insertUserRole(user);
return rows;
}
这里边就简单的三个函数,里边也没检测也不会抛异常,直接做成事务让事务管理器去搞了。但是事务是怎么检测这玩意儿运没运行完了我还没搞明白,等找一篇事务工作原理介绍的文章看看。