2

我正在尝试同时更新“用户”文档中的多个字段。但是,我只想更新一些字段而不是替换整个文档,而我似乎无法避免后者。我这样做的方法如下所示:

public void mergeUser(User user) {
    Update mergeUserUpdate = new Update();
    mergeUserUpdate.set("firstName", user.getFirstName());
    mergeUserUpdate.set("lastName", user.getLastName());
    mergeUserUpdate.set("username", user.getUsername());

    mongoTemplate.updateFirst(new Query(Criteria.where("_id").is(user.getId())), mergeUserUpdate, User.class);
}

我的用户对象确实包含其他字段 - 一个password字段就是其中之一 - 但如果在它被立即替换为空字符串或完全删除之前将其设置为一个值。所以在数据库中,这个:

{
  "_id" : ObjectId("4fc34563c3276c69248271d8"),
  "_class" : "com.test.User",
  "password" : "d26b7f5c0ed888e46889dd1e3d217816d070510596f495e156e9efe4b035fec5a1fe1be643955359",
  "username" : "john@gmail.com",
  "alias" : "john"
}

在我调用方法后被替换为mergeUser

{
  "_id" : ObjectId("4fc34563c3276c69248271d8"),
  "_class" : "com.test.User",
  "username" : "john@gmail.com",
  "firstName" : "John",
  "lastName" : "Doe",
  "address" : {
    "addressLine1" : ""
  }
}

如果我查看 Update 对象,我会看到它包含以下内容:

{$set={firstName=John, lastName=Doe, username=john@gmail.com}}

这对我来说是正确的,根据我对 MongoDB$set函数的理解,这应该只设置指定的值。因此,我希望密码字段保持不变,并相应地添加或更改其他字段。

作为一般讨论点,我最终试图实现某种“合并”功能,Spring 将自动神奇地检查提供的 User 对象中存在哪些字段,并且只使用填充的值更新数据库,而不是所有领域。这在理论上应该是可能的,我会想到的。有人知道这样做的好方法吗?

这是我的用户对象以防万一:

/**
 * Represents an application user.
 */
@Document(collection = "users")
public class User {

    @Id
    private String id;

    @NotEmpty( groups={ChangePasswordValidationGroup.class} )
    private String password;

    @Indexed
    @NotEmpty
    @Email
    private String username;

    private String firstName;

    private String lastName;

    private Date dob;

    private Gender gender;

    private Address address;

    public enum Gender {
        MALE, FEMALE
    }

    // /////// GETTERS AND SETTERS ///////////

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public Date getDob() {
        return dob;
    }

    public void setDob(Date dob) {
        this.dob = dob;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public Gender getGender() {
        return gender;
    }

    public void setGender(Gender gender) {
        this.gender = gender;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }
}
4

2 回答 2

2

上面的代码确实工作得很好。我犯了一个愚蠢的错误,在正确更新后我继续保存用户对象,用新文档替换它。

于 2012-05-29T08:41:06.833 回答
1

使用 Spring MongoTemplate 有另一种解决方案来更新没有某些字段的实体:

DBObject userDBObject = (DBObject) mongoTemplate.getConverter().convertToMongoType(user);
//remove unnecessary fields    
userDBObject.removeField("_id");
userDBObject.removeField("password");

//Create setUpdate & query
Update setUpdate = Update.fromDBObject(new BasicDBObject("$set", userDBObject));
mongoTemplate.updateFirst(new Query(Criteria.where("_id").is(user.getId())), setUpdate , User.class);

//Or use native mongo
//mongoTemplate.getDb().getCollection("user").update(new BasicDBObject("_id",user.getId())
        , new BasicDBObject("$set", userDBObject), false, false);

因为它使用自动转换器,所以当您的实体有很多字段时非常有用。

于 2014-03-28T04:34:19.553 回答