You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.17 16:35:27