如何使用存储库接口在 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 Boot 应用程序的同一个域类上同时使用 Spring Data JPA 和 Spring Data Elasticsearch 存储库?