记一次mongoDB-@Document(collection = “XXX“)配置的探索

直接开门见山,大多数会用mongoDB开发的都知道实体类上加上

@Document(collection = “XXX”)

可以直接将操作指定到对应的XXX 集合中,但是对应第一次玩mongoDB的我却浑然不知(留下没有技术的眼泪)。起因是因为每次调用都需要指定collectionName,如下

Long totalCount = mongoOperations.count(query, reqDTO.getClass(),"refund_error");
List<OperatorBillingSummaryPO> list = mongoOperations.find(query, OperatorBillingSummaryPO.class,"operator_billing_summary");

如果不指定collectionName则用默认的类名(等下会讲到源码)
对于处女座的我而言看着特别不舒服,很想把他们全部规整化,于是便有了以下的探索

1、方案一

首先我第一个想到的是将MongoOperations(或者MongoTemplate)在业务代码上所用到
操作(新增修改查询那些)全部用统一MongoDBUtil工具类封装,每次都通过工具类进行操作,collectionName 则通过枚举匹配,或者传入Class类的类名进行分解拆分(这种方法比较土),将RefundErrorInfoBO 转成 refund_error 类似这样,除此之外,也可以用ThreadLocal或者缓存的方式查询,因为思路比较简单就不贴代码了。

2、方案二

由于方案一不合适,直接去spring-data-mongodb的官网搜(https://docs.spring.io/spring-data/mongodb/docs/current/reference/html/#mongodb.mapping-usage.events),

请添加图片描述
于是发现有个生命周期事件,可通过继承 AbstractMongoEventListener 事件监听器进行事件监听,不过只能拿到event事件的实体source、事件处理后的Document以及我朝思暮想的collectionName,但并不能设置具体值,MongoMappingEvent 类如下

public class MongoMappingEvent<T> extends ApplicationEvent {

   private static final long serialVersionUID = 1L;
   private final @Nullable Document document;
   private final @Nullable String collectionName;

   /**
    * Creates new {@link MongoMappingEvent}.
    *
    * @param source must not be {@literal null}.
    * @param document can be {@literal null}.
    * @param collectionName can be {@literal null}.
    */
   public MongoMappingEvent(T source, @Nullable Document document, @Nullable String collectionName) {

      super(source);
      this.document = document;
      this.collectionName = collectionName;
   }

   /**
    * @return {@literal null} if not set.
    */
   public @Nullable Document getDocument() {
      return document;
   }

   /**
    * Get the collection the event refers to.
    *
    * @return {@literal null} if not set.
    * @since 1.8
    */
   public @Nullable String getCollectionName() {
      return collectionName;
   }

   /*
    * (non-Javadoc)
    * @see java.util.EventObject#getSource()
    */
   @SuppressWarnings({ "unchecked" })
   @Override
   public T getSource() {
      return (T) super.getSource();
   }
}

3、方案三

最直接的方法,也就是看源码
首先从find方法入手
org.springframework.data.mongodb.core.MongoTemplate#find(org.springframework.data.mongodb.core.query.Query, java.lang.Class)
在这里插入图片描述

进入设置方法
org.springframework.data.mongodb.core.MongoTemplate#determineCollectionName
请添加图片描述

获取PersistentEntity
org.springframework.data.mapping.context.MappingContext#getRequiredPersistentEntity(java.lang.Class<?>)
从Debug模式进入可以看到已经获取到collection了(此时已添加@Document(collection = “refund_error”)注解)
请添加图片描述

于是返回上层的设置方法
org.springframework.data.mapping.context.AbstractMappingContext#getPersistentEntity(org.springframework.data.util.TypeInformation<?>)
entity不为空,在此退出,可以看到entity是通过AbstractMappingContext内置的HashMap常量persistentEntities获取到的

请添加图片描述

persistentEntities是怎么设置进来的呢?点击可以看到调用的put方法,在此方法下
org.springframework.data.mapping.context.AbstractMappingContext#addPersistentEntity(org.springframework.data.util.TypeInformation<?>)

请添加图片描述
entity还是被设置了,继续往上看createPersistentEntity方法

createPersistentEntity有三个实现类,看MongoMappingContext的方法
org.springframework.data.mongodb.core.mapping.MongoMappingContext#createPersistentEntity
,此时还是被设置请添加图片描述
继续往上,终于找到了~
在这里插入图片描述
此方法的意思是使用给定的 TypeInformation 创建一个新的 BasicMongoPersistentEntity。如果@Document设置了collection则用设置的值,没有则将集合名称设为实体类型名,实体名则用org.springframework.data.mongodb.MongoCollectionUtils#getPreferredCollectionName获取,并将首字母大写字母转为小写。

至于org.springframework.data.mapping.context.AbstractMappingContext#addPersistentEntity(java.lang.Class<?>) 什么时候调用的,则是在SpringAOP初始化bean时,会调用初始化方法afterPropertiesSet
在这里插入图片描述

进而进入org.springframework.data.mapping.context.AbstractMappingContext#initialize,再调用org.springframework.data.mapping.context.AbstractMappingContext#addPersistentEntity(java.lang.Class<?>)实现整个属性的设置

思路比较简单,有疏漏的望各位大佬指点,小弟先告退了
请添加图片描述

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值