说几个弊端
为了解决这个问题,《阿里巴巴泰山版java开发手册》推荐在Service层之下独立出一个通用业务处理层(Manager层)
相比较传统的MVC,主要增加了 Manager 层, 它有如下特征:
实际开发中,
简言之, Manager 层提供原子服务接口,Service 层负责依据业务逻辑来调用原子接口。
举个例子说明一下Manager层的使用场景
需求:
反手就是一顿突突啊
package com.artisan.service;
import com.artisan.dao.UserDao;
import com.artisan.response.ResponseData;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.util.concurrent.TimeUnit;
/**
* @author 小工匠
* @version 1.0
* @mark: show me the code , change the world
*/
@Service
public class ServiceWithoutManager {
private final boolean APP = true;
@Autowired
private UserDao userDao;
@Transactional(rollbackFor = Throwable.class)
public ResponseData<String> buiz(Long idCard, Long name) {
// 验证 1 假设 DB操作 校验
String var1 = doDBCheck1();
// 验证 2 假设 DB操作 校验
String var2 = doDBCheck2();
// 业务 APP -- DB校验 --- 自动创建用户 -- 返回用户信息
// 网页 -- DB校验 --- -- 返回用户信息
doBiz(var1,var2);
return ResponseData.success("success");
}
@SneakyThrows
private void doBiz(String a ,String b) {
if(APP) {
// 模拟业务耗时
TimeUnit.MILLISECONDS.sleep(1200);
}else {
}
}
@SneakyThrows
private String doDBCheck2() {
// 模拟业务耗时
TimeUnit.MILLISECONDS.sleep(500);
return "";
}
@SneakyThrows
private String doDBCheck1() {
// 模拟业务耗时
TimeUnit.MILLISECONDS.sleep(1000);
return "";
}
}
这有啥子问题? 常规操作啊…
每日一博 - 常见的Spring事务失效&事务不回滚案例集锦
让我们来分析分析
对于复杂业务的不可预计的情况,长时间占用同一个 connection 连接应该尽量避免,应该尽量缩短占用时间。
@Transactional 注解, AOP 实现,本质就是在目标方法执行前后进行拦截。 在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。
当 Spring 遇到该注解时,会自动从数据库连接池中获取 connection,并开启事务然后绑定到 ThreadLocal 上,对于@Transactional注解包裹的整个方法都是使用同一个connection连接。
如果出现了耗时的操作,比如三方接口调用,业务逻辑复杂,大数据处理等就会导致占用这个connection的时间过长,数据库连接一直被占用不释放。一旦类似操作过多,进而导致数据库连接池耗尽。
将数据在 service 层准备好,然后传递给 manager 层,由 manager 层添加@Transactional事务注解进行数据库操作, 尽量减少大事务带来的危害。