Spring Mongo人口一一

Spring Mongo Populator one by one

我在 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
}

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

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

添加自定义杰克逊 2 Reader

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 Populator

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

使用 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
}

}