Spring Mongo Populator 一一

Posted

技术标签:

【中文标题】Spring Mongo Populator 一一【英文标题】:Spring Mongo Populator one by one 【发布时间】:2020-06-27 21:51:25 【问题描述】:

我在 Kotlin 上使用 MongoDB 和 Spring,我希望我的应用程序在启动时填充 MongoDB 集合。 (并在每次启动时清理它)

我的问题是,如果我正在填充的某些数据有问题,我如何才能一一填充数据以便容错?

我的代码:

@Configuration
class IndicatorPopulator 
    @Value("classpath:indicatorData.json")
    private lateinit var data: Resource

    @Autowired
    private lateinit var indicatorRepository: IndicatorRepository

    @Bean
    @Autowired
    fun repositoryPopulator(objectMapper: ObjectMapper): Jackson2RepositoryPopulatorFactoryBean 
        val factory = Jackson2RepositoryPopulatorFactoryBean()
        indicatorRepository.deleteAll()
        factory.setMapper(objectMapper)
        factory.setResources(arrayOf(data))
        return factory
    

我正在寻找的是这样的:

@Bean
@Autowired
fun repositoryPopulator(objectMapper: ObjectMapper): Jackson2RepositoryPopulatorFactoryBean 
    val factory = Jackson2RepositoryPopulatorFactoryBean()
    indicatorRepository.deleteAll()
    factory.setMapper(objectMapper)
    val arrayOfResources: Array<Resource> = arrayOf(data)
    for (resource in arrayOfResources)
            try
             factory.setResources(resource)
             catch(e: Exception)
                 logger.log(e.message)
            

    
    return factory

任何关于如何做类似事情的想法都会有所帮助...... 提前致谢。

【问题讨论】:

因此,如果许多资源中的某些资源包含格式错误的 JSON 数据,您想记录错误并跳过“坏”资源吗?你想用Jackson2RepositoryPopulatorFactoryBean 或类似的东西来做吗? 差不多......不仅是格式错误的 JSON 数据,如果它们是有效的 JSON,但不适合实体 _class。 @ShaharWider 您能提供您的反馈吗? 【参考方案1】:

没有内置支持您的请求,但您可以通过调整几个类轻松提供。

添加自定义 Jackson 2 阅读器

public class CustomJackson2ResourceReader implements ResourceReader 

    private static final Logger logger = LoggerFactory.getLogger(CustomJackson2ResourceReader.class);

    private final Jackson2ResourceReader resourceReader = new Jackson2ResourceReader();

    @Override
    public Object readFrom(Resource resource, ClassLoader classLoader) throws Exception 
        Object result;
        try 
            result = resourceReader.readFrom(resource, classLoader);
         catch(Exception e) 
            logger.warn("Can't read from resource", e);
            return Collections.EMPTY_LIST;
        
        return result;
    

添加自定义 Jackson 2 填充器

public class CustomJackson2RepositoryPopulatorFactoryBean extends Jackson2RepositoryPopulatorFactoryBean 
    @Override
    protected ResourceReader getResourceReader() 
        return new CustomJackson2ResourceReader();
    

配置

@SpringBootApplication
public class DemoApplication 

    public static void main(String[] args) 
        SpringApplication.run(DemoApplication.class, args);
    

    @Bean
    public AbstractRepositoryPopulatorFactoryBean repositoryPopulator(ObjectMapper objectMapper, KeyValueRepository keyValueRepository) 
        Jackson2RepositoryPopulatorFactoryBean factory = new CustomJackson2RepositoryPopulatorFactoryBean();
        keyValueRepository.deleteAll();
        factory.setMapper(objectMapper);
        factory.setResources(new Resource[]new ClassPathResource("badclassname.json"), new ClassPathResource("good.json"), new ClassPathResource("malformatted.json"));
        return factory;
    


我上传了一个工作示例here

【讨论】:

【参考方案2】:

使用 Sagar 的 Reader & Factory,我刚刚对其进行了调整以满足我的需求(Kotlin,并从同一个 JSON 文件中读取资源)得到了这个答案:

@Configuration
class IndicatorPopulator 

@Value("classpath:indicatorData.json")
private lateinit var data: Resource

@Autowired
private lateinit var indicatorRepository: IndicatorRepository

@Autowired
@Bean
fun repositoryPopulator(objectMapper: ObjectMapper): Jackson2RepositoryPopulatorFactoryBean 
    val factory: Jackson2RepositoryPopulatorFactoryBean = CustomJackson2RepositoryPopulatorFactoryBean()
    factory.setMapper(objectMapper)
    // inject your Jackson Object Mapper if you need to customize it:
    indicatorRepository.deleteAll()


    val resources = mutableListOf<Resource>()
    val readTree: ArrayNode = objectMapper.readTree(data.inputStream) as ArrayNode
    for (node in readTree)
        resources.add( InputStreamResource(node.toString().byteInputStream()))
    
    factory.setResources(resources.toTypedArray())
    return factory

【讨论】:

以上是关于Spring Mongo Populator 一一的主要内容,如果未能解决你的问题,请参考以下文章

从产品展示页面谈谈Hybris系列之二: DTO, Converter和Populator

spring 整合 mongo

使用 spring data mongo 插入 Mongo 文档

将 mongo 查询转换为 spring-data-mongo 查询

如何使用 mongo 搜索集合并返回子文档列表(Spring-data-mongo)

使用 mongoTemplate 在 spring-data-mongo Java 中进行 Mongo 聚合查询