如何在Spring中强制MongoDB的唯一字段



我有一个pojo,有两个字段需要是唯一的,id和电子邮件。因此,我将@Indexed(unique = true)注释添加到必要的字段中,如

public class User {
@Id
@Indexed(unique = true)
private String id;
@Indexed(unique = true)
private String email;
private int money;

然后我测试了它,它没有被强制执行。所以我用谷歌搜索了一下,我在这里找到了一个以前的答案- Spring Data: MongoDB文档中的唯一字段,随后删除了该集合,将spring.data.mongodb.auto-index-creation=true添加到我的应用程序。属性文件,然后重试。

然而,唯一字段仍然没有强制执行!我看到有另一个使用ensureIndex()的答案,但它也有一个从未回答过的伟大评论-Why do we need to use the annotation if all the work is done on mongoTemplate?

所以既然这个问题足够老,显然唯一有效的答案是贬值的(新的方法是使用createIndex()),我认为是时候发布一个新版本了。是否有可能要求mongo集合中的列从Spring Boot是唯一的?

这个问题似乎在当前最新的春季启动数据MongoDB版本(v3.0.4)中得到了修复。

我在自己的个人项目中使用Spring Boot v3.0.4和Java 17/Kotlin进行了测试,我的文档类最终是这样的:

@Document
class User(@Indexed(unique = true) var username: String) {
@Id
var id: String? = null
var name: String? = null
var surname: String? = null
}

重要:我确实需要添加spring.data.mongodb.auto-index-creation=true到我的应用程序。属性文件,只有在做这个在MongoDB上删除集合之后,我得到了在我的用户API上实际执行的字段。

在我的例子中,刚刚添加了上述所有配置(@Indexed(unique=true)spring.data.mongodb.auto-index-creation=true)之后,当试图插入一个与现有用户具有相同username的用户时,我开始得到以下错误:

curl -v --location 'http://localhost:9000/user' 
--header 'Authorization: Bearer <token>' 
--header 'Content-Type: application/json' 
--data-raw '{
"username": "testuser1",
"name": "Test",
"surname": "User 1"
}'
*   Trying 127.0.0.1:9000...
* Connected to localhost (127.0.0.1) port 9000 (#0)
> POST /user HTTP/1.1
> Host: localhost:9000
> User-Agent: curl/7.81.0
> Accept: */*
> Authorization: Bearer <token>
> Content-Type: application/json
> Content-Length: 76
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 409 
< Vary: Origin
< Vary: Access-Control-Request-Method
< Vary: Access-Control-Request-Headers
< X-Content-Type-Options: nosniff
< X-XSS-Protection: 0
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-Frame-Options: DENY
< Content-Type: application/json
< Transfer-Encoding: chunked
< Date: Tue, 14 Mar 2023 18:48:08 GMT
< 
* Connection #0 to host localhost left intact
{"cause":{"cause":null,"message":"Write operation error on server localhost:27017. Write error: WriteError{code=11000, message='E11000 duplicate key error collection: test.user index: username dup key: { username: "testuser1" }', details={}}."},"message":"Write operation error on server localhost:27017. Write error: WriteError{code=11000, message='E11000 duplicate key error collection: test.user index: username dup key: { username: "testuser1" }', details={}}."}

检查DB中的记录,发现它确实限制并停止了写操作。

此测试中使用的其他版本:

kotlin("jvm") - 1.7.22
kotlin("plugin.spring") - "1.7.22"
MongoDB - 4.4.10
Ubuntu (host) - 22.04

最新更新