MongoRepository.save()前1-2次无法更新字段,需如何调整?
这种前几次更新没反应、之后又正常的情况我之前在旧版本Spring Data MongoDB里碰到过,结合你用的Spring Boot 1.5.4.RELEASE + MongoDB 3.2.2技术栈,大概率和实体状态管理、缓存或者MongoDB的更新策略有关,给你几个具体的调整方向:
1. 改用局部更新替代“先查询再保存”的模式
你当前的代码是先查询实体、修改字段再保存,这种方式依赖Spring Data对实体“脏数据”的识别,但在旧版本里,List类型字段的变更有时候不会被正确标记为脏数据,导致前几次save操作实际上没触发数据库更新。
换成直接针对字段的局部更新,绕过实体状态检查,更可靠:
// 用Query和Update做局部更新 Query query = new Query(Criteria.where("id").is(merchantBean.getId())); Update update = new Update().set("features", abc.getFeatures()); merchantRepository.updateFirst(query, update);
如果你的Repository继承了MongoRepository,需要自己定义这个updateFirst方法(或者用MongoTemplate直接操作):
public interface MerchantRepository extends MongoRepository<Merchant, String> { void updateFirst(Query query, Update update); }
2. 检查并清理Spring Data的缓存影响
如果你的findOne方法加了@Cacheable注解,第一次查询的旧数据会被缓存起来,后续修改后缓存没及时刷新,导致你拿到的还是旧实体,自然更新不生效。
解决方法:
- 在save方法上添加
@CacheEvict注解,更新后清除对应缓存:
@CacheEvict(value = "merchants", key = "#merchant.id") @Override Merchant save(Merchant merchant);
- 或者暂时禁用
findOne方法的缓存,验证是否是缓存导致的问题。
3. 配置MongoDB的写关注点(Write Concern)
MongoDB 3.2.2默认的写关注点可能是Acknowledged,但如果是在副本集环境下,前几次写操作可能因为节点同步延迟,看起来没生效。可以显式设置更高的写关注点,确保写操作被大多数节点确认:
在application.properties里添加:
spring.data.mongodb.write-concern=MAJORITY
4. 验证实体字段的映射正确性
确认你的features字段注解是否正确,避免字段名不匹配导致更新无效:
import org.springframework.data.mongodb.core.mapping.Field; public class Merchant { // ...其他字段 @Field("features") // 确保和MongoDB集合里的字段名一致 private List<String> features; // getter和setter }
优先推荐第一种局部更新的方式,因为它直接操作数据库,不受Spring Data实体状态管理的限制,能彻底解决这类“前几次不生效”的问题。
内容的提问来源于stack exchange,提问作者Jayesh Choudhary

