我需要编写一个应用程序,可以使用spring-data和MongoDB进行复杂的查询。我开始使用MongoRepository,但在查找示例或理解语法时,我遇到了复杂的查询。
我说的是这样的查询:
@Repository
public interface UserRepositoryInterface extends MongoRepository<User, String> {
List<User> findByEmailOrLastName(String email, String lastName);
}
或者使用基于JSON的查询,我尝试了反复试验,因为我没有得到正确的语法。即使在阅读了MongoDB文档之后(由于语法错误而无法工作的示例)。
@Repository
public interface UserRepositoryInterface extends MongoRepository<User, String> {
@Query("'$or':[{'firstName':{'$regex':?0,'$options':'i'}},{'lastName':{'$regex':?0,'$options':'i'}}]")
List<User> findByEmailOrFirstnameOrLastnameLike(String searchText);
}
在阅读了所有文档之后,似乎mongoTemplate
的文档比MongoRepository
好得多。我指的是以下文档:
http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/
你能告诉我哪一个更方便更强大吗?mongoTemplate
还是MongoRepository
?两者都是一样成熟还是一个比另一个缺少更多的特征?
3条答案
按热度按时间fhg3lkii1#
“方便”和“功能强大”在某种程度上是相互矛盾的目标。存储库比模板方便得多,但后者当然可以给予您更细粒度地控制要执行的内容。
由于存储库编程模型可用于多个Spring Data模块,您可以在Spring Data MongoDB参考文档的常规部分找到更多深入的文档。
TL;DR
我们通常建议采用以下方法:
1.从存储库抽象开始,使用查询派生机制或手动定义的查询来声明简单的查询。
1.对于更复杂的查询,请将手动实现的方法添加到存储库中(如此处所述)。使用
MongoTemplate
实现。详情
对于您的示例,它看起来像这样:
1.为自定义代码定义接口:
1.为这个类添加一个实现,并遵循命名约定,以确保我们可以找到这个类。
1.现在让你的基本仓库接口扩展自定义接口,基础设施将自动使用你的自定义实现:
这样你基本上就得到了选择:所有容易声明的东西都放在
UserRepository
中,所有更好地手动实现的东西都放在CustomUserRepository
中。此处记录了自定义选项。06odsfpq2#
FWIW,关于多线程环境中的更新:
MongoTemplate
提供**“原子”开箱即用操作**updateFirst
、updateMulti
、findAndModify
、upsert
。..允许您在单个操作中修改文档。这些方法使用的Update
对象也允许您仅针对相关字段。MongoRepository
只提供基本CRUD操作find
,insert
,save
,delete
,适用于包含所有字段的POJO。这迫使您要么分几个步骤更新文档(1.find
要更新的文档,2.从返回的POJO中修改相关字段,然后3.save
it),或者使用@Query
手工定义自己的更新查询。在多线程环境中,如e。例如,一个Java后端具有多个REST端点,单方法更新是一种方法,以减少两个并发更新覆盖彼此更改的可能性。
例如:给定一个像这样的文档:
{ _id: "ID1", field1: "a string", field2: 10.0 }
和两个不同的线程并发地更新它。..使用
MongoTemplate
,它看起来有点像这样:并且文档的最终状态总是
{ _id: "ID1", field1: "another string", field2: 15.0 }
,因为每个线程只访问DB一次 * 并且 * 只有指定的字段被更改。而使用
MongoRepository
的相同案例场景看起来像这样:最终文档是
{ _id: "ID1", field1: "another string", field2: 10.0 }
还是{ _id: "ID1", field1: "a string", field2: 15.0 }
,取决于哪个save
操作最后命中DB。(NOTE:即使我们按照注解中的建议使用Spring Data的
@Version
注解,也不会有太大的改变:save
操作中的一个将抛出OptimisticLockingFailureException
,并且最终文档仍然是上述操作中的一个,只有一个字段更新,而不是两个。)所以我认为**
MongoTemplate
是一个更好的选择**,除非你有一个非常复杂的POJO模型,或者出于某种原因需要MongoRepository
的自定义查询功能。khbbv19g3#
这个答案可能有点延迟,但我建议避免整个存储库路线。你得到的方法很少有很大的实用价值。为了使它工作,您遇到了Java配置的废话,您可能会花费数天甚至数周的时间,而没有文档中的太多帮助。
相反,使用
MongoTemplate
路线并创建您自己的数据访问层,这将使您从Spring程序员面临的配置噩梦中解放出来。MongoTemplate
确实是工程师的救星,他们可以轻松地构建自己的类和交互,因为它具有很大的灵活性。结构可以是这样的:1.创建一个将在应用程序级别运行的
MongoClientFactory
类,并给予一个MongoClient
对象。您可以将其实现为Singleton或使用EnumSingleton(这是线程安全的)1.创建一个数据访问基类,您可以从该基类继承每个域对象的数据访问对象)。基类可以实现一个方法来创建一个MongoTemplate对象,您可以使用特定于类的方法进行所有DB访问
1.每个域对象的每个数据访问类都可以实现基本方法,也可以在基类中实现这些方法