前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Repository解析---以Mongo Repository为例

Spring Repository解析---以Mongo Repository为例

作者头像
方丈的寺院
发布2019-08-05 17:24:14
1.1K0
发布2019-08-05 17:24:14
举报
文章被收录于专栏:方丈的寺院

摘要

Spring 为java web 开发领域提供了大量的优秀的框架,第三方包,大大解放了生产力,本文主要介绍Spring Repository在连接数据库这边做的一些封装,并以Mongo Repository为例,详细阐述下Repository实现机制,本文基于spring-data-mongo1.10.4

问题

在使用Repository的时候,相信很多人都有下面的疑问,本文就是致力于解决这些疑惑

  1. Repository 做了什么,和Template有什么区别,两者如何用
  2. Repository是如何做到写个方法名,就可以了(没有查询条件)
  3. Repository什么时候检查方法名的
  4. Repository可不可以只返回部分值,支持返回Long,String等类型吗
  5. 如何去查看实际发送给DB的语句

Repository 实现

一个根据userId找帖子的Repository方法

代码语言:javascript
复制
@Repository
public interface PostRepository extends MongoRepository<Post,String> {
    Post findTopByUserId(Long userId);
}

Bean 加载

  1. MongoRepositoryFactoryBean 继承自RepositoryFactoryBeanSupport抽象类,提供了一个afterProperties()方法,在属性被加载后,进行RepositoryFactorySupport实例的设置
  2. RepositoryFactoryBeanSupport 抽象类中的afterProperties()方法中调用initAndReturn(),然后调用getRepository()设置定义注解为@Repository的代理类。在这里即设置了PostRepository 的代理类,同时构建了Repository接口的方法,并做校验 ResolveQuery方法中构建了PartTreeMongoQuery其中类的成员变量PartTree存储了Repository的方法,这样不用每次实际去调用方法.PartTree 将方法通过parser转换成一个主谓语,by前后语义
    1. private final PartTree.Subject subject;
    2. private final PartTree.Predicate predicate;

方法调用

  1. 实际调用方法时,在上面Bean加载时代理了QueryExecutorMethodInterceptor
    1. result.addAdvice(new RepositoryFactorySupport.QueryExecutorMethodInterceptor(information, customImplementation, target));
  2. 所以调用时,就会执行QueryExecutorMethodInterceptor.invoke方法
    1. private Object doInvoke(MethodInvocation invocation) throws Throwable {
    2. Method method = invocation.getMethod();
    3. Object[] arguments = invocation.getArguments();
    4. Method actualMethod;
    5. if(this.isCustomMethodInvocation(invocation)) {
    6. actualMethod = this.repositoryInformation.getTargetClassMethod(method);
    7. return this.executeMethodOn(this.customImplementation, actualMethod, arguments);
    8. } else if(this.hasQueryFor(method)) {
    9. // 执行RepositoryQuery.execute方法
    10. return ((RepositoryQuery)this.queries.get(method)).execute(arguments);
    11. } else {
    12. actualMethod = this.repositoryInformation.getTargetClassMethod(method);
    13. return this.executeMethodOn(this.target, actualMethod, arguments);
    14. }
    15. }
  3. 调用AbstractMongoQuery.execute去执行query 这个方法里包含了构建query 条件,发送查询语句的所有逻辑 PartTreeMongoQuery.createQuery根据之前的partTree结构将查询进行数值绑定,构成真正的query。 然后执行时调用的是MongoTemplate
  1. public Object execute(Object[] parameters) {
  2. MongoParameterAccessor accessor = new MongoParametersParameterAccessor(this.method, parameters);
  3. // 构建query条件
  4. Query query = this.createQuery(new ConvertingParameterAccessor(this.operations.getConverter(), accessor));
  5. this.applyQueryMetaAttributesWhenPresent(query);
  6. ResultProcessor processor = this.method.getResultProcessor().withDynamicProjection(accessor);
  7. String collection = this.method.getEntityInformation().getCollectionName();
  8. MongoQueryExecution execution = this.getExecution(query, accessor, new ResultProcessingConverter(processor, this.operations, this.instantiators));
  9. return execution.execute(query, processor.getReturnedType().getDomainType(), collection);
  10. }

答案

  1. Repository 做了什么,和Template有什么区别,两者如何用 答: Repository是在Template上面进行了进一步的封装,减少了重复代码。 多数据源的时候需要为repository指定具体的template
  2. Repository是如何做到写个方法名,就可以了(没有查询条件) 答: 构建一个语义化的parse
  3. Repository什么时候检查方法名的 答:Bean加载的时候
  4. Repository可不可以只返回部分值,支持返回Long,String等类型吗 答: 不可以返回部分值,PartTree没有解析返回值语句
  5. 如何去查看实际发送给DB的语句 org.springframework.data.mongodb.repository.query.MongoQueryCreator 类进行了正在的实际的query语句生成 当然一个粗暴的方法就是开启org.springframework的debug日志
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2018-04-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 方丈的寺院 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 摘要
  • 问题
  • Repository 实现
    • Bean 加载
      • 方法调用
      • 答案
      相关产品与服务
      对象存储
      对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档