使用EasyExcelListener没有事务的解决办法

在Spring Boot项目中使用 easyexcel 导入excel时,如果选择分批导入数据,因为是用直接new创建的 AnalysisEventListener 的实现类,传入的service或mapper参数来保存到数据库,会出现每次保存都提交了事务,如果后面数据出现了异常,之前批次导入的数据不会回滚。

解决办法

手动管理事务

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
@Slf4j
public class TransactionalExcelListener<T> extends AnalysisEventListener<T> {

// 事务管理
private final DataSourceTransactionManager dataSourceTransactionManager;
private final TransactionStatus transactionStatus;

private static final int BATCH_COUNT = 100;

List<T> dataList = new ArrayList<>();

private final IService<T> service;

public TransactionalExcelListener(
DataSourceTransactionManager dataSourceTransactionManager,
TransactionDefinition transactionDefinition,
IService<T> service) {
this.service= service;

this.dataSourceTransactionManager = dataSourceTransactionManager;
DefaultTransactionDefinition definition = new DefaultTransactionDefinition(transactionDefinition);
// 设置事务隔离级别
definition.setIsolationLevel(TransactionDefinition.ISOLATION_DEFAULT);
// 手动开启事务
this.transactionStatus = dataSourceTransactionManager.getTransaction(definition);
}

@Override
public synchronized void invoke(T rowData, AnalysisContext analysisContext) {
boolean hasCompleted = transactionStatus.isCompleted();
// 如果事务已经关闭
if (hasCompleted) {
return;
}
dataList.add(rowData);

if (dataList.size() >= BATCH_COUNT) {
saveData();
}
}

@Override
public void doAfterAllAnalysed(AnalysisContext context) {
boolean hasCompleted = transactionStatus.isCompleted();
if (hasCompleted) {
return;
}
saveData();
log.info("所有数据解析完成!");
//提交事务
dataSourceTransactionManager.commit(transactionStatus);
log.info("当前事务已提交");
}

@Override
public void onException(Exception exception, AnalysisContext context) throws Exception {
log.info("导入出现异常,事务回滚");
dataSourceTransactionManager.rollback(transactionStatus);
}

/**
* 加上存储数据库
*/
private void saveData() {
log.info("{}条数据,开始存储数据库!", dataList.size());
service.saveBatch(dataList);
log.info("存储数据库成功!");
dataList.clear();
}

}
  • Copyrights © 2020-2023 夕子学姐
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信