栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Automatic index creation will be disabled by default as of Spring Data MongoDB 3.x.

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Automatic index creation will be disabled by default as of Spring Data MongoDB 3.x.

spring data mongoDb 根据注释自动创建索引将于3之后默认关闭

报警如下:

    Please use 'MongoMappingContext#setAutoIndexCreation(boolean)' or override 'MongoConfigurationSupport#autoIndexCreation()' to be explicit.
	However, we recommend setting up indices manually in an application ready block. You may use index derivation there as well.

	> -----------------------------------------------------------------------------------------
	> @EventListener(ApplicationReadyEvent.class)
	> public void initIndicesAfterStartup() {
	>
	>     IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
	>
	>     IndexResolver resolver = new MongoPersistentEntityIndexResolver(mongoMappingContext);
	>     resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
	> }
	> -----------------------------------------------------------------------------------------

其实这个自动创建索引的开关我们关了就不会报这个警告了,但是同时那些带有@Indexed注解的字段也不会自动的创建索引了 那给个警告什么意思呢?官方是这么说的 就是让我们自己主动的去创建索引,我这个版本是2.多,默认还是开启自动配置的,那首先就是要关闭自动配置,然后去按照官方写法创建索引
一、使用spring自动配置的MongoTemplate

application.yml

spring:
	data:
	    mongodb:
	      host: 192.168.1.1					# mongo地址
	      database: database				# 要连接的数据库
	      auto-index-creation: false		# 关闭自动索引创建

以下引至官方示例

1、为单个类(@Document)创建索引
@Component
class MyListener {

  @EventListener(ContextRefreshedEvent.class)
  public void initIndicesAfterStartup() {

    MappingContext, MongoPersistentProperty> mappingContext = mongoTemplate
                .getConverter().getMappingContext();

    IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);

    IndexOperations indexOps = mongoTemplate.indexOps(DomainType.class);
    resolver.resolveIndexFor(DomainType.class).forEach(indexOps::ensureIndex);
  }
}
2、为所有类(@Document)创建索引 (一般用这个)
@Component
class MyListener{

  @EventListener(ContextRefreshedEvent.class)
  public void initIndicesAfterStartup() {

    MappingContext, MongoPersistentProperty> mappingContext = mongoTemplate
        .getConverter().getMappingContext();

    // consider only entities that are annotated with @Document
    mappingContext.getPersistentEntities()
                            .stream()
                            .filter(it -> it.isAnnotationPresent(Document.class))
                            .forEach(it -> {

    IndexOperations indexOps = mongoTemplate.indexOps(it.getType());
    resolver.resolveIndexFor(it.getType()).forEach(indexOps::ensureIndex);
    });
  }
}
二、自定义配置类继承 AbstractMongoClientConfiguration

第二种就是我使用的了,自定义一些MongoTemplate的配置,因为我要用到spring config+bus自动刷新配置,要在一些Bean上面加个注解

application.yml (因为自定义配置了, 这些字段也可以自定义)

spring:
	data:
    mongodb:
      host: mongodb://192.168.1.1:27017 	# mongo地址,跟上面有些差别
      database: database					# 数据库

配置类:

@Configuration
@ConfigurationProperties(prefix = "spring.data.mongodb")
public class ToolsMongoConfig extends AbstractMongoClientConfiguration implements ApplicationContextAware {
	
    private String host;
    
    private String database;
		
	
    private ApplicationContext applicationContext;


    @Override
    public MongoClient mongoClient() {
        return MongoClients.create(this.host);
    }

    @Override
    protected String getDatabaseName() {
        return this.database;
    }

    @Bean(name = "mongoTemplate")
    @Override
    public MongoTemplate mongoTemplate() throws Exception {
        return new MongoTemplate(super.mongoDbFactory(),super.mappingMongoConverter());
    }


	// 关闭自动配置:
    @Override
    protected boolean autoIndexCreation() {
        return false;
    }

   	//添加监听事件
    @EventListener(ContextRefreshedEvent.class)
    public void initIndicesAfterStartup() throws Exception {
        MongoTemplate mongoTemplate = mongoTemplate();
        //mongo 映射
        MappingContext, MongoPersistentProperty> mappingContext = mongoTemplate
                .getConverter().getMappingContext();

        //映射解析器
        IndexResolver resolver = new MongoPersistentEntityIndexResolver(mappingContext);

        //获取启动类
        Map beansWithAnnotation = applicationContext.getBeansWithAnnotation(SpringBootApplication.class);
        Object runApplicationObj = beansWithAnnotation.values().iterator().next();

        //获取启动类所在的包名
        String pckname = runApplicationObj.getClass().getPackage().getName();
        //自定义扫描器,扫描该包名下的带有 @Document 注解的类
        ScanAndBeanLoader scanAndBeanLoader = new ScanAndBeanLoader(pckname);
        Set beanDefinitionHolders = scanAndBeanLoader.doScanByAnnotation(Document.class.getName());
        //把这些类交给解析器去创建索引
        for(BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders){
            String beanClassName = beanDefinitionHolder.getBeanDefinition().getBeanClassName();
            Class docClass = Class.forName(beanClassName);

            IndexOperations indexOps = mongoTemplate.indexOps(docClass);
            resolver.resolveIndexFor(docClass).forEach(indexOps::ensureIndex);
        }
    }

    public String getHost() {
        return host;
    }

    public void setHost(String host) {
        this.host = host;
    }

    public String getDatabase() {
        return database;
    }

    public void setDatabase(String database) {
        this.database = database;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }
}
关于自定义配置类和官方写法不一样的问题:

在自定义配置类中我尝试使用官方的方法去使用,但是在mappingContext.getPersistentEntities()
获取映射类的时候,获取不到,里面是空的,翻了翻源码,大致看到了两边处理是不一样的(源码比较难啃),所以我们不用mappingContext中获取这个映射类了,我们自定义扫描器,扫描启动类所在的包里面所有带有 @Document 的类,然后交给那个IndexResolver去检查和创建索引

自定义扫描类:
public class ScanAndBeanLoader {

    
    private String pkgPath;


    private ScanAndBeanLoader(){}
    public ScanAndBeanLoader(String pkgPath){
        this.pkgPath = pkgPath;
    }

    
    public Set doScanBySuperClass(String superClassName){
        BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
        CustomerClassPathBeanDefinitionScanner customScan = new CustomerClassPathBeanDefinitionScanner(registry , false);

        //自定义过滤条件
        TypeFilter customFilter = new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, @NonNull MetadataReaderFactory metadataReaderFactory) throws IOException {
                //是具体的类,非抽象类  并且  具有  这个注解
                return metadataReader.getClassMetadata().isConcrete() && Objects.equals(metadataReader.getClassMetadata().getSuperClassName(), superClassName);
            }
        };
        customScan.addIncludeFilter(customFilter);          //添加include

        return customScan.doScan(pkgPath);
    }
    
    public Set doScanByAnnotation(String annotationClassName){
        BeanDefinitionRegistry registry = new SimpleBeanDefinitionRegistry();
        CustomerClassPathBeanDefinitionScanner customScan = new CustomerClassPathBeanDefinitionScanner(registry , false);

        //自定义过滤条件
        TypeFilter customFilter = new TypeFilter() {
            @Override
            public boolean match(MetadataReader metadataReader, @NonNull MetadataReaderFactory metadataReaderFactory) throws IOException {
                //是具体的类,非抽象类  并且  具有  这个注解
                return metadataReader.getClassMetadata().isConcrete() && metadataReader.getAnnotationMetadata().hasAnnotation(annotationClassName);
            }
        };
        customScan.addIncludeFilter(customFilter);          //添加include

        return customScan.doScan(pkgPath);
    }


}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/929994.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号