Java中如何实现按目标zip文件存在状态精准清理对应数据库表
代码优化方案
核心调整逻辑
当前代码的核心问题是全表删除操作早于文件扫描环节执行,没有基于目录下实际存在的文件类型判断清理范围,同时存在单例Bean的成员变量并发安全隐患。调整时保持原有业务流程不变,仅做以下小范围改动:
- 流程顺序反转:先对目标目录做一次预扫描,标记是否存在对应命名标识的zip文件
- 删除逻辑条件化:仅当对应类型文件存在时,才执行目标表的全量删除,无对应文件的表不做任何操作
- 修正并发隐患:将原成员变量
isEquity改为方法内局部变量,避免单例Bean被多线程调用时出现数据写表错位
调整后完整代码
@Service public class IImporter { private final static Logger log = LoggerFactory.getLogger(IImporter.class); private final static String EQU_FILE_TAG = "EQUFULLFILE"; private final static String NONEQU_FILE_TAG = "NONEQUFULLFILE"; @Autowired private IFullreader IFullreader; @Autowired private ZipWalker zipWalker; @Autowired private SessionFactory sessionFactory; @Transactional public void importDir(Path indir) throws IOException { // 预扫描目录,标记两类文件是否存在 boolean hasEquFile = false; boolean hasNonEquFile = false; // 用try-with-resources确保Stream资源关闭 try (Stream<Path> pathStream = Files.walk(indir, 1, FOLLOW_LINKS)) { List<Path> zipFiles = pathStream .filter(Files::isRegularFile) .filter(f -> f.getFileName().toString().endsWith(".zip")) .sorted() .toList(); for (Path zipFile : zipFiles) { String fileName = zipFile.getFileName().toString(); if (fileName.contains(EQU_FILE_TAG)) { hasEquFile = true; } if (fileName.contains(NONEQU_FILE_TAG)) { hasNonEquFile = true; } } // 按标记执行对应表的清理,无对应文件则跳过 if (hasEquFile) { log.info("检测到权益类全量文件,执行EquData表全量清理"); sessionFactory.getCurrentSession().createQuery("delete from EquData").executeUpdate(); } else { log.info("未检测到带EQUFULLFILE标识的文件,跳过EquData表清理"); } if (hasNonEquFile) { log.info("检测到非权益类全量文件,执行NonEquData表全量清理"); sessionFactory.getCurrentSession().createQuery("delete from NonEquData").executeUpdate(); } else { log.info("未检测到带NONEQUFULLFILE标识的文件,跳过NonEquData表清理"); } log.info("开始处理目录: {}", indir.toString()); // 复用预扫描得到的zip文件列表做后续处理,避免重复遍历目录 zipFiles.forEach(f -> zipWalker.processZipFile(f, this::importFile)); } } private void importFile(Path path) { // 改为局部变量,避免单例Bean的并发安全问题 boolean isEquity = path.getFileName().toString().contains(EQU_FILE_TAG); if (isEquity) { // 原有权益类文件读取、数据写入逻辑保持不变 } else { // 原有非权益类文件读取、数据写入逻辑保持不变 } } }
关键改动说明
- 预扫描阶段一次性把目录下所有合规zip文件读取成列表,既可以判断文件存在性,又能避免原流程中重复遍历两次目录的性能浪费
- 全表删除操作完全和文件存在性绑定,不存在对应类型文件时绝对不执行删除,避免无意义的全表数据清空
- 修正了原代码里
Files.walk返回的Stream未关闭的资源泄漏问题,同时把路径后缀判断从全路径字符串匹配改为文件名匹配,避免路径目录名带.zip后缀导致的误判 - 移除了作为成员变量的
isEquity,避免Spring单例Bean在多线程并发调用时,不同请求的判断值互相覆盖,导致数据写错表的潜在问题
内容的提问来源于stack exchange,提问作者Symonds
相关产品推荐
相关产品推荐

