【问题标题】:Duplicate Key error while trying to update a field of an Object in MongoDB SpringBoot尝试更新 MongoDB SpringBoot 中对象的字段时出现重复键错误
【发布时间】:2019-02-05 11:08:47
【问题描述】:

我正在尝试更新我的对象上的一个字段,然后尝试保存它。将要调用的控制器中的代码是这样的。

ApplicationUser user = applicationUserRepository.findByVerificationCode(verificationCode);
if(user != null) {
    user.setVerified(true);//trying to change a value in a field
    applicationUserRepository.save(user);
    return new ResponseEntity<>(user,new HttpHeaders(),HttpStatus.OK);
}

当我尝试执行此代码时,我收到此错误

E11000 重复键错误索引:myapp.applicationUser.$id dup key: { : 0 };

我在 ApplicationUser 类中明确定义 Id。 我的ApplicationUser类是这样的

public class ApplicationUser {
    @Id
    private long id;
    private String username;
    private String password;
    private String name;
    private String email;
    private String verificationCode;
    private boolean verified=false;

    private List<Company> boughtCompanies;

    public long getId() {
        return id;
    }

    public String getUsername() {
        return username;
    }

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

    public String getPassword() {
        return password;
    }

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

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getVerificationCode() {
        return verificationCode;
    }

    public void setVerificationCode(String verificationCode) {
        this.verificationCode = verificationCode;
    }

    public List<Company> getBoughtCompanies() {
        return boughtCompanies;
    }

    public void setBoughtCompanies(List<Company> boughtCompanies) {
        this.boughtCompanies = boughtCompanies;
    }

    public boolean isVerified() {
        return verified;
    }

    public void setVerified(boolean verified) {
        this.verified = verified;
    }       
}

我在这里做错了什么或者我应该如何处理?谢谢。

【问题讨论】:

    标签: java spring mongodb spring-boot


    【解决方案1】:

    编辑: 将@Id 字段设置为字符串。在 mongo 中将长值作为 ID 是不好的。 同样正如 M. Wajdi 所说,您需要将 setter 添加到 id 字段。


    我看到您正在执行文档更新,因此您应该使用 applicationUserRepository.save() 而不是 applicationUserRepository.insert()。 (其实我一直都用save)。

    说明:

    插入总是尝试在数据库中引入一个新对象。 第一次创建 ApplicationUser 时,insert 在数据库中创建对象并为其分配一个 ID。 但是,如果您阅读它,更新它并尝试再次插入它,Mongo 会理解您实际上是在尝试引入具有相同 ID 的新对象(而不是在该对象中执行更新)。 这就是为什么你会得到那个异常,重复键。

    【讨论】:

    • 对不起,我从一开始就使用 save ,但仍然遇到同样的错误。我试过插入但同样的问题。我也更新了问题
    • 能否附上applicationUserRepository的代码?此外,您可以尝试将 @Id 字段从 long 更改为 String。客户端生成的ID一般是String格式的UUID。
    • 我将 Id 从 Long 更改为 String 并且它有效。非常感谢。
    【解决方案2】:

    您尝试插入具有相同 ID 的现有用户 函数插入我认为你应该用更新函数来改变它

    【讨论】:

    • 我正在使用 save 但我仍然收到同样的错误。
    • 必须生成用户id
    【解决方案3】:

    你没有使用你的ID的setter,所以你需要把它作为自动增量

    public class ApplicationUser {
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        private long id;
        private String username;
        private String password;
        private String name;
        private String email;
        private String verificationCode;
        private boolean verified=false;
    
        private List<Company> boughtCompanies;
    
        public long getId() {
            return id;
        }
    
        public String getUsername() {
            return username;
        }
    
        public void setUsername(String username) {
            this.username = username;
        }
    
        public String getPassword() {
            return password;
        }
    
        public void setPassword(String password) {
            this.password = password;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getEmail() {
            return email;
        }
    
        public void setEmail(String email) {
            this.email = email;
        }
    
        public String getVerificationCode() {
            return verificationCode;
        }
    
        public void setVerificationCode(String verificationCode) {
            this.verificationCode = verificationCode;
        }
    
        public List<Company> getBoughtCompanies() {
            return boughtCompanies;
        }
    
        public void setBoughtCompanies(List<Company> boughtCompanies) {
            this.boughtCompanies = boughtCompanies;
        }
    
        public boolean isVerified() {
            return verified;
        }
    
        public void setVerified(boolean verified) {
            this.verified = verified;
        }       
    }
    

    【讨论】:

      【解决方案4】:

      同时选择长(或任何其他原始)作为Mongo @id,那么您必须满足ID生成,否则每次都会提供长默认值i.e.0

      关于自动增量排序,请参阅此处Auto increment sequence in mongodb using java

      否则将@Id 设为String 类型,mongo 会自动生成十六进制类型的默认Id,更多信息请参阅https://docs.mongodb.com/manual/reference/method/ObjectId/

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-18
        • 2011-09-03
        • 1970-01-01
        • 2021-02-03
        • 2013-07-07
        • 1970-01-01
        相关资源
        最近更新 更多