【问题标题】:Spring Mongo Repository is unable to match String to ObjectId in _id fieldSpring Mongo 存储库无法将字符串与 _id 字段中的 ObjectId 匹配
【发布时间】:2020-10-16 19:23:02
【问题描述】:

我有一个带有 String Id 的数据类,我将它保存到带有 null 值的 mongoDB 中以获取自动生成的替换。

@Document(collection="applications")
@TypeAlias(Constants.Application)
public class DataApplication implements IApplication{

@Id
@Field("id")
private String id = null;

...
}

这按预期工作,但是我面临一个问题,我似乎无法从 Spring Mongo Repo 中找到 findById。它能够毫无问题地持久化和检索,像创建 BSON 一样

{
   "_id" : ObjectId("5ef9a579bafa09b36225e743c"),
   Other fields and things
}

但是,这似乎专门用于尝试使用 id 字段进行查找时。 它没有使用我指定的 Id 字段名称,这很奇怪,但是当我一次检索多个对象时,它们按预期转换回 POJO,我不认为这是一个问题。

据我所见,这似乎是 MongoDB 将值存储为 ObjectId 的结果,因为当我将应用程序拉入 Java 时,当我持久化具有 String Id 值的对象时,我能够通过 Id 检索比较,或者当我创建匹配除 Id 之外的所有字段的示例时,但是当我设置要比较的 Id 时,示例失败。

Prevent Spring Data for Mongo to convert ids to ObjectId 似乎是相关的,因为它提到了底层查询结构,不幸的是我似乎有相反的问题。

【问题讨论】:

  • 我可以通过获取所有、获取分页或仅通过示例获取并匹配非 Id 字段来检索它们。该值似乎只是作为字符串的 ObjectId。
  • 确定有帮助吗?

标签: java mongodb spring-boot spring-data


【解决方案1】:

@Field 注解用于定义文档字段的自定义元数据。例如:

@Field(targetType = DECIMAL128)
private BigDecimal value;

@Field("fName")
private String firstName;

当您定义@Field("id") private String id = null; 时,它被解释为字段id 为另一个字段id,而不是文档标识符字段_id。因为,注解的name 属性被指定为“id”。您也可以在以下示例中使用Person Pojo 类验证这一点:

public class Person {
    
    @Field("id")
    private String id = null;

    private String name;
    
    public Person(String name) {
        this.name = name;
    }

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

    // other get / set methods ...

    public String toString() {
       return "id: " + id + ", " + name;
    }
}

使用MongoRepository 方法在person 集合中插入和查询文档:

Person p1 = new Person("J.Doe");
//p1.setId("000");
repo.insert(p1);

List<Person> list = repo.findAll();
list.forEach(System.out::println);

这将插入一个文档(从mongo shell 查询)并将toString 表示打印为:

{ "_id" : ObjectId("5ef5c92b70babc5a961350e5"), "name" : "J.Doe", "_class" : "com.example.demo.Person" }

打印为:id: null, J.Doe

如果你取消注释代码p1.setId("000");并再次运行它,你会发现如下:

{ "_id" : ObjectId("5ef5cab8306d071b13d3c16e"), "id" : "000", "name" : "J.Doe", "_class" : "com.example.demo.Person" }

并且,打印为:id: 000, J.Doe

代码运行良好。请注意两个字段,_idid@Field 用于自定义文档字段。

要正确指示id 字段将用于_id 文档键字段,您可以使用以下内容。创建文档时,_id 值将是驱动程序生成的ObjectId

  • id 字段注释为@Id@MongoId@Field(不带 nameattribute)。
  • 根本不注释。

注解注意事项:

  • @Id: 在字段级别应用以标记用于标识的字段 目的。
  • @MongoId: 在字段级别应用以标记用于标识的字段 目的。接受可选的 FieldType 来自定义 id 转换。
  • @Field:应用于字段级别,它允许描述名称和 字段的类型,因为它将在 MongoDB BSON 中表示 文件因此允许名称和类型不同于 类的字段名称以及属性类型。

【讨论】:

  • 不幸的是,事实并非如此。奇怪的是,它似乎只是将 id 字段视为数据库中的 _id 。至少就 BSON 而言,它似乎将 id 匹配到 _id 并返回,即使我认为它应该像你描述的那样表现。所以我会看到 { "_id" : ObjectId("5ef5b9bd5aa2275b7b0d131b") } 如果我没有设置它或 { "_id" : "000" } 如果我这样做了。
  • 你怎么知道id字段被视为_id?您可以将@Field("id") 更改为@Field("id2") 看看会发生什么。
  • 我的帖子中有一些输入错误 - 我会在几分钟内更正它。
  • 我已经更正了我的答案以解释正在发生的事情。希望对您有所帮助。
  • 另见这篇文章,当在 Pojo 对象中未设置引用字段(即 null 值)时,应用程序不会在插入的文档中创建该字段:@987654323 @.
猜你喜欢
  • 2021-03-27
  • 2020-02-09
  • 2021-11-30
  • 1970-01-01
  • 2018-06-25
  • 2014-07-30
  • 1970-01-01
  • 2016-07-03
相关资源
最近更新 更多