如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?

Posted

技术标签:

【中文标题】如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?【英文标题】:How to find collections by its nested object's objectId in Spring Data using repository interface? 【发布时间】:2014-10-15 23:35:29 【问题描述】:

我在 MongoDB 中有一个集合,其中包含这样的项目:


    "_id" : ObjectId("53e4d31d1f6b66e5163962e3c"),
    "name" : "bob",
    "nestedObject" : 
        "_id" : ObjectId("53f5a623cb5e4c1ed4f6ce67")
        //more fields...
    

此项目的 Java 表示如下:

public class SomeObject 
    @Id
    private String id;
    private String name;
    private NestedObject nestedObject;

    //getters and setters

Repository 接口定义如下:

public interface SomeObjectRepository extends MongoRepository<SomeObject, String> 
    public List<SomeObject> findByName(String name);
    public List<SomeObject> findByNestedObjectId(String id);
    //some other find functions

现在,findByName(String name) 正在正常工作,但 findByNestedObjectId(String id) 什么也没返回。

问题是:是否可以使用存储库接口通过其嵌套对象的属性找到集合项?如果没有,解决此问题的推荐方法是什么?是否可以不重新实现整个存储库?

【问题讨论】:

【参考方案1】:

nestedObject id 需要转换成一个

 org.bson.types.ObjectId 

然后 ObjectId 可以与存储库方法一起使用

findAllByNestedObject_Id(ObjectId)

【讨论】:

感谢您的贡献。您能否提供工作示例代码来说明这一点。请查看本指南“How to Answer”以改进它。【参考方案2】:

我将以下内容用于 Spring-boot;对我来说就像魅力一样:

@Query("nestedObjectProperty.$id : ?0")

【讨论】:

【参考方案3】:

这在 1.6.2 spring-data-mongodb 上对我有用。但是最新版本有问题。

public interface SomeObjectRepository extends MongoRepository<SomeObject, String> 
    public List<SomeObject> findByName(String name);
    @Query("nestedObjectProperty._id :  $oid : ?0")
    public List<SomeObject> findByNestedObjectId(String id);
    //some other find functions

【讨论】:

【参考方案4】:

我已经想出了如何解决这个问题。

将参数类型改为org.bson.types.ObjectId;来自字符串

public List<SomeObject> findByNestedObjectId(ObjectId id);

当你调用它时使用

 repositoryName.findByNestedObjectId(new ObjectId(theIdString));

【讨论】:

这适用于我使用 1.8.2 版本。 findByNestdObjectId(String id);不起作用,我必须使用 ObjectId 而不是字符串才能使其工作......【参考方案5】:

如果NestedObject 看起来像这样:

class NestedObject 

  @Id String id;

您输入查询的String 值是有效的ObjectId 查询:

findByNestdObjectId(String id);

应该可以。如果觉得不方便,请在JIRA 中创建票证并提供一个小测试用例来重现它。

【讨论】:

这里有同样的问题:***.com/questions/35196033/… 你能看看@OliverGierke 吗?非常感谢【参考方案6】:

Spring-data-mongodb 不会在查询操作的嵌套类中自动将 _id 字段转换为 ObjectId 类型。您应该手动转换它。例如:

public List<SomeObject> findByNestedObjectId(String id) 
    Query query = Query.query(new Criteria("nestedObject._id", convertToObjectId(id)));
    return mongoTemplate.find(query, SomeObject.class);


Object convertToObjectId(Object id) 
    if (id instanceof String && ObjectId.isValid(id)) 
        return new ObjectId(id);
    
    return id;

【讨论】:

最终我在处理这个存储库的服务中使用了不同的逻辑。在那里我有一个方法getByNestedObjectId,它首先调用NestedObject no = nestedObjectRepo.findOne(id),然后调用SomeObject result = someObjectRepo.findByNestedObject(no) 你不介意这会因为访问数据库 2 次而第二次是更复杂的查询而降低执行效率吗? 这不正确。嵌套的 id 应该会自动转换。也用于查询执行。 @Oliver Gierke:我和提问者有同样的经历,如果不正确,我的代码将无济于事。但是很抱歉我犯了一个错误,现在我知道它已经在后一个版本上升级了。 The problem exists at version 1.0.4. 1.0.4 的什么?如果那是 Spring Data MongoDB,那么古代可能是描述该版本的最佳方式:)。当前版本是 1.5.2。【参考方案7】:

您可以使用@Query 指定存储库使用的mongoDB 查询。我不是 100% 下面的查询是准确的,但有一些事情:

public interface SomeObjectRepository extends MongoRepository<SomeObject, String> 
    public List<SomeObject> findByName(String name);
    @Query("nestedObject._id : ?0")
    public List<SomeObject> findByNestedObjectId(String id);
    //some other find functions

【讨论】:

我已经尝试过了,它正在工作,但不适用于_id。只要您通过 _id 以外的任何方式查询数据库,这是一个很好的答案。 ID 的处理方式不同。 mongo shell 中的示例:db.somecollection.find( 'nestedObject._id' : "magicId") 不返回任何内容,而 db.somecollection.find( 'nestedObject._id' : ObjectId("magicId") ) 正常。我试图将ObjectId(?0) 添加到@Query,但后来我从java 中得到了JSON 解析异常。不过,感谢您的快速回复:) 是否可以在 NestedObject 中添加“@Id nestedObjectId”等?那么查询肯定应该使用它。

以上是关于如何使用存储库接口在 Spring Data 中通过其嵌套对象的 objectId 查找集合?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Spring Data 存储库上测试 Spring 的声明式缓存支持?

使用 Spring-Data-Solr 注入存储库

延迟加载 Spring Data JPA 存储库

如何在 Spring Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?

我需要为哪些实体创建 Spring Data 存储库?

了解 Spring Data JPA @NoRepositoryBean 接口