Spring Mongo 仅通过新 POJO 的非空字段进行更新

Posted

技术标签:

【中文标题】Spring Mongo 仅通过新 POJO 的非空字段进行更新【英文标题】:Spring Mongo update by only not null fields of new POJO 【发布时间】:2020-09-25 22:37:45 【问题描述】:

用户模型:

@Document(collection = "USER")
public class UserModel 
    private String id;
    private String username;
    @Indexed(unique = true)
    private String email;
    private String password;
    private String firstName;
    private String lastName;

用户存储库:

@Repository
public interface UserRepository extends MongoRepository<UserModel, String> 

    Optional<UserModel> findByEmail(String email);
    Optional<UserModel> findByUsername(String username);

像这样保存用户文档:

@Autowired
UserRepository userRepo;

public someMethod() 
    UserModel user = new UserModel();
    //Set all fields....
    userRepo.save(user);

尝试像这样更新:

@Autowired
UserRepository userRepo;

public someMethod() 
    UserModel user = new UserModel();
    user.setId("A valid Id got from database by last insert")
    user.setFirstName("New first name");
    // Remaining fields are null now
    userRepo.save(user);

这里的 null 值将由 MongoRepository 插入。

我可以通过什么设置告诉 MongoRepository 在更新时避免空值?

如果我们通过MongoTemplate updateFirst() 方法执行此操作,我们必须为 POJO 的所有字段添加if 条件。在这种情况下,最好的解决方案是什么?

【问题讨论】:

这能回答你的问题吗? Spring Data MongoDB - ignore empty objects 【参考方案1】:

尝试先从数据库中获取用户,然后更新您的数据并保存在数据库中。

UserModel user = userRepo.findById(id); // Fetch from database
user.setFirstName("New first name");    // Update the data
userRepo.save(user);                    // Save in the database

或使用自定义查询仅更新选定的字段。这里要使其动态化,从UserModel 创建一个Map&lt;String, Object&gt; 并删除空值。

ObjectMapper oMapper = new ObjectMapper();
Map<String, Object> dataMap = oMapper.convertValue(user, Map.class);
map.values().removeIf(Objects::isNull);

现在在Update 中设置地图,然后在数据库中更新。

Update update = new Update();
dataMap.forEach(update::set);
Query query = new Query().addCriteria(where("_id").is(id));
mongoTemplate.update(UserModel.class).matching(query).apply(update).first();

【讨论】:

这需要一个额外的查询。我们的目标是通过一个更新查询和更少的代码来完成。 你使用了 Jackson ObjectMapper。正确的?好吧,以某种方式制作 JSON 是个好主意。让我们看看有没有其他好的方法来做到这一点。 @iamcrypticcoder 是的。如果您更新的节点是动态的,那么我认为这是一个好方法。或者,如果它们已修复,那么只需添加 Update 是一个好方法。 @Eklvya 我对此 JSON 转换的意见。基本上我心里有这个。这种转换不需要时间吗?此外,与 GSON 相比,Jackson 不能很好地处理小负载。我的意思是杰克逊需要的时间。 @iamcrypticcoder 取决于您是否使用单例(创建一个 bean),那么它不会花费太多时间。如果您手动创建 Map 则可以避免这种情况。

以上是关于Spring Mongo 仅通过新 POJO 的非空字段进行更新的主要内容,如果未能解决你的问题,请参考以下文章

无法从 Spring Boot REST 中的 Hibernate POJO 返回 JSON

Mongo - 忽略属性被持久化

Spring Boot 连接到运行的 mongo 容器的 MongoDB 副本集

如何在 Spring Boot 中将 mongo db update 运算符应用为 $inc

如何在 Spring Boot 中从 MongoDb 中仅读取特定的 JSON 节点

spring mongo数据异常,通过xml配置