事务的使用:
一、@Transactional 注解:
AOP代码实现的:在调用this.syncLocal(incoming))方法的前后,开启和提交事务。
调用方
→ Spring 代理对象.method()
→ 拦截器:开启事务
→ 真正执行目标方法
→ 拦截器:提交 / 回滚
二、transactionTemplate (精细化给某段代码加事务控制)
TransactionTemplate 是编程式开启,不依赖代理,私有方法里也能用。
-
TransactionManager.getTransaction() // 开启事务、绑定到当前线程
-
执行 syncLocal(...) // 里面的 JDBC/MyBatis 自动加入这个事务
-
commit(成功)或 rollback(异常)
@Override
public void fullSync() {
SingleCellDataPermissionHelper.ignore(() -> {
List<CellSingleLimsTrialGroup> incoming = loadFromLims();
if (CollectionUtils.isEmpty(incoming)) {
throw new ServiceException("LIMS部门数据为空,终止同步");
}
transactionTemplate.executeWithoutResult(status -> syncLocal(incoming));
cellSingleLimsTrialGroupTreeCache.refresh();
});
}
//不能使用@Transactional注解会失效
private void syncLocal(List<CellSingleLimsTrialGroup> incoming) {
Map<Long, CellSingleLimsTrialGroup> incomingMap = toIdMap(incoming);
Map<Long, CellSingleLimsTrialGroup> existingMap = toIdMap(cellSingleLimsTrialGroupDao.selectAllKeys());
List<CellSingleLimsTrialGroup> toInsert = new ArrayList<>();
List<CellSingleLimsTrialGroup> toUpdate = new ArrayList<>();
List<Long> toDelete = new ArrayList<>();
for (Map.Entry<Long, CellSingleLimsTrialGroup> entry : incomingMap.entrySet()) {
if (existingMap.containsKey(entry.getKey())) {
toUpdate.add(entry.getValue());
} else {
toInsert.add(entry.getValue());
}
}
for (Map.Entry<Long, CellSingleLimsTrialGroup> entry : existingMap.entrySet()) {
if (!incomingMap.containsKey(entry.getKey())) {
toDelete.add(entry.getKey());
}
}
if (CollectionUtils.isNotEmpty(toDelete)) {
cellSingleLimsTrialGroupDao.deleteByIds(toDelete);
}
if (CollectionUtils.isNotEmpty(toUpdate)) {
cellSingleLimsTrialGroupDao.updateByIds(toUpdate);
}
if (CollectionUtils.isNotEmpty(toInsert)) {
cellSingleLimsTrialGroupDao.insertBatch(toInsert);
}
log.info("检测部门树全量同步完成, incoming={}, insert={}, update={}, delete={}",
incomingMap.size(), toInsert.size(), toUpdate.size(), toDelete.size());
}