【问题标题】:Spring Boot MongoDB @Query Annotation Mapping ErrorSpring Boot MongoDB @Query 注解映射错误
【发布时间】:2018-06-21 09:33:47
【问题描述】:

当我得到一个在 java 对象中不存在的属性时,我执行此操作时出错。我的记录对象有

@Document
public class Record{
    @Field("RecordIdentifier")
    String RecordIdentifier;
    ...
}

我的 MongoRepository 对象有

public interface RecordRepository extends MongoRepository<Record,String> {

    @Query("{ 'RecordIdentifier' : ?0 }
    public Record findByRecordIdentifier(String RecordIdentifier);

}

在 MongoDB 中我有

{
    'RecordIdentifier' : 'D'
}

但是当我调用查询方法时

@Autowired
RecordRepository repository

...

repository.findAll();
repository.findByRecordIdentifier("D");

repository.findAll() 返回正常并正确映射所有内容,但 findByRecordIdentifier() 返回错误,指出它无法在 Record 对象中找到属性“recordIdentifier”。如果我在 Record 对象中将字段的名称从“RecordIdentifier”更改为“recordIdentifier”,它可以正常工作,但为什么我不能将该字段称为“RecordIdentifier”

真正奇怪的是,如果我将 Mongo 文档更改为

{
 'Record_Identifier' : 'D'
}

即使查询不应再返回任何内容,我仍然会收到相同的错误,因为它现在指向一个不存在的字段。有人可以帮我吗?如果需要,我可以提供更多详细信息。

【问题讨论】:

  • 请为@Query 加上双引号和双引号,你忘了最后一个

标签: spring mongodb spring-boot spring-data spring-data-mongodb


【解决方案1】:

您忘记在@Query 末尾添加“。请使用

@Query("{ 'RecordIdentifier' : ?0 }")

而不是

@Query("{ 'RecordIdentifier' : ?0 })

【讨论】:

  • 您的帖子可能会受益于某些应用格式。见这里stackoverflow.com/editing-help
  • 请澄清这如何回答本页顶部的问题。我的印象是您正在对@pvpkiram 的答案发表评论如果这实际上您正在尝试的,那么请使用您的评论权限并删除此非答案。
【解决方案2】:

如果您不想更改字段名称,其他选择是使用自定义转换器

public class PersonReadConverter implements Converter<Document, Person> {

  public Person convert(Document source) {
    Person p = new Person((ObjectId) source.get("_id"), (String) source.get("name"));
    p.setAge((Integer) source.get("age"));
    return p;
  }
}

注册他们使用

<mongo:mapping-converter>
  <mongo:custom-converters base-package="com.acme.**.converters" />
</mongo:mapping-converter>

供您参考https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongo.custom-converters

【讨论】:

    【解决方案3】:

    要了解为什么会发生这种情况,您需要了解 spring-data 的工作原理。

    Spring 数据存储库主要使用方法名称。它根据方法名称创建查询。
    Spring-data 将制定查询以获取 findBy (在您的情况下为 RecordIdentifier )之后指定的字段。但是在编译时,它会检查您是否提供了有效的字段,以便它可以准备正确的查询。它通过检查该字段的实体类(在您的情况下为记录)来实现。

    注意:如果字段名称是abc,那么你必须指定方法名称为findByAbc(注意大写A)

    例如在你的情况下,如果你只指定这个(没有@Query

     public Record findByRecordIdentifier(String RecordIdentifier);
    

    它将尝试在数据库中搜索字段recordIdentifier

    如果您不希望 spring-data 根据方法名称自行制定查询,那么您可以像现在一样使用@Query 指定它。

    但它不起作用的原因是因为您通过指定方法名称来混淆 spring-data 以便它尝试自行制定查询。

    解决方案:
    1. 将字段名称更改为命名约定recordIdentifier。如果你这样做,那么你的 Repository 方法就不需要@Query
    2. 将方法名称(省略findByfindAllBy 前缀)更改为类似

    @Query("{ 'RecordIdentifier' : ?0 }
    public Record getRecordByRecordIdentifier(String RecordIdentifier);
    

    【讨论】:

    • 解释很好,但解决方案不如 Debopam 的干净。如果您将建议的解决方案更改为此,我会投票赞成。
    • 我不想更改项目中所有字段的命名约定,因为带有 java 对象的包被其他项目使用。我尝试了解决方案 #2,但仍然遇到同样的错误。
    【解决方案4】:

    更改字符串RecordIdentifier;到字符串recordIdentifier;并在类中添加 getter/setter 方法。您的字段声明不符合 Java Bean 命名标准,因此反射找不到合适的 setter 方法。

    【讨论】:

    • 还有大约 1000 个其他字段,并且这个 java 对象所在的包正在被其他项目使用,所以如果我需要更改每个字符串的命名约定,将会产生很大的影响。它确实有效,但我只想将其用作最后的手段
    • 唯一的其他选择是使用 monogTemplate 编写您自己的查询执行它并填充 POJO 从 BSON 获取数据。这太低了,工作量也一样,但变化会在一个地方,即在你的 DAO 层中。
    猜你喜欢
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 2020-01-26
    • 2018-07-11
    • 2019-07-13
    • 2018-06-07
    • 1970-01-01
    相关资源
    最近更新 更多