如何为Mongock实现@RollbackExecution方法(Player类扩展场景)
解决方案
核心思路是区分迁移时自动添加的默认Parameters和业务逻辑中创建的Parameters,这里提供两种可靠实现方式:
方式一:用临时标记字段批量处理(推荐)
通过给迁移时修改的文档添加临时标记,回滚时仅处理带标记的文档,效率更高且无需额外存储:
1. 修改@Execution方法(添加标记)
改用MongoTemplate执行批量更新,同时给目标文档添加临时标记字段(无需修改Player实体类):
@Execution public void execution(MongoTemplate mongoTemplate) { // 给所有无parameters字段的文档设置默认值,并添加迁移标记 mongoTemplate.updateMulti( Query.query(Criteria.where("parameters").exists(false)), Update.update("parameters", new Player.Parameters(false, false)) .set("_migrated_params", true) // 临时标记字段,用于回滚识别 ); }
2. 实现@RollbackExecution方法
仅移除带标记文档的parameters字段,并清理临时标记:
@RollbackExecution public void rollback(MongoTemplate mongoTemplate) { // 匹配所有带迁移标记的文档,删除parameters字段并移除标记 mongoTemplate.updateMulti( Query.query(Criteria.where("_migrated_params").is(true)), Update.unset("parameters") .unset("_migrated_params") ); }
方式二:记录修改的文档ID(适合依赖Repository的场景)
如果必须通过PlayerRepository操作,可以记录所有被迁移修改的文档ID,回滚时精准处理:
1. 修改@Execution方法(记录ID)
创建临时迁移记录类,存储本次迁移修改的文档ID:
@Execution public void execution(PlayerRepository playerRepository, MongoTemplate mongoTemplate) { List<String> modifiedIds = playerRepository.findAll() .stream() .filter(player -> player.getParameters() == null) .map(player -> { player.setParameters(new Player.Parameters(false, false)); playerRepository.save(player); return player.getId(); }) .collect(Collectors.toList()); // 将修改的ID存入临时集合,用于回滚 mongoTemplate.save( new MigrationRecord("player_params_migration", modifiedIds), "migration_records" ); } // 临时迁移记录实体类 private static class MigrationRecord { private String migrationId; private List<String> documentIds; public MigrationRecord(String migrationId, List<String> documentIds) { this.migrationId = migrationId; this.documentIds = documentIds; } // 省略getter/setter }
2. 实现@RollbackExecution方法
根据记录的ID精准回滚,并清理迁移记录:
@RollbackExecution public void rollback(PlayerRepository playerRepository, MongoTemplate mongoTemplate) { MigrationRecord record = mongoTemplate.findOne( Query.query(Criteria.where("migrationId").is("player_params_migration")), MigrationRecord.class, "migration_records" ); if (record != null) { record.getDocumentIds().forEach(id -> { Player player = playerRepository.findById(id).orElse(null); if (player != null) { player.setParameters(null); playerRepository.save(player); } }); // 删除迁移记录 mongoTemplate.remove(record, "migration_records"); } }
内容的提问来源于stack exchange,提问作者krzysiekcr
相关产品推荐
相关产品推荐

