当前位置: 首页 > 知识库问答 >
问题:

Spring batch上载CSV文件并相应地插入数据库

胡鸿远
2023-03-14

我的项目有这样的要求,用户上传一个CSV文件,该文件必须推送到mysql数据库。我知道我们可以使用Spring批处理来处理大量记录。但我找不到任何教程/示例代码来满足我的这一要求。我遇到的所有教程都只是将CSV文件名硬编码在其中,如下所示:

https://spring.io/guides/gs/batch-processing/

我需要使用用户上传的文件并进行相应的处理。如果您有任何帮助,我们将不胜感激。。

如果没有使用Spring batch,是否有其他方法将上载的CSV数据插入mysql?

共有2个答案

夏侯昆琦
2023-03-14

我是通过混合Spring MVC(RestController)和Spring Batch来实现的。Spring MVC帮助将csv文件作为多部分请求上传。然后,通过将上载的CSV传递给Spring作业,异步调用Spring批处理。一旦Spring作业收到csv文件,它就通过读取、处理和写入DB作业来执行Spring批处理。

薛欣荣
2023-03-14

请将此作为主要参考:http://walkingtechie.blogspot.co.uk/2017/03/spring-batch-csv-file-to-mysql.html这说明了如何使用Batch将CSV文件导入MySQL数据库。

然而,正如您所说的,所有示例都假设一个硬代码文件不是您想要的。

在下面的代码中,重要的位(与我提供的链接中的示例不同)是控制器,它获取多部分文件并将其保存在临时文件夹中。然后将文件名作为参数传递给作业:

JobExecution jobExecution = jobLauncher.run(importUserJob, new JobParametersBuilder()
                .addString("fullPathFileName", fileToImport.getAbsolutePath())
                .toJobParameters());

最后,import Reader使用参数fullPathFileName加载用户上传的文件:

      @Bean
      public FlatFileItemReader<Person> importReader(@Value("#{jobParameters[fullPathFileName]}") String pathToFile) {
        FlatFileItemReader<Person> reader = new FlatFileItemReader<>();
        reader.setResource(new FileSystemResource(pathToFile));

下面是完整的代码(未测试,但它包含大多数组件),让您了解:

@Configuration
@EnableBatchProcessing
public class BatchConfig{

    @Bean
    public ResourcelessTransactionManager batchTransactionManager(){
        ResourcelessTransactionManager transactionManager = new ResourcelessTransactionManager();
        return transactionManager;
    }

    @Bean
    protected JobRepository jobRepository(ResourcelessTransactionManager batchTransactionManager) throws Exception{
        MapJobRepositoryFactoryBean jobRepository = new MapJobRepositoryFactoryBean();
        jobRepository.setTransactionManager(batchTransactionManager);
        return (JobRepository)jobRepository.getObject();
    }

    @Bean
    public JobLauncher jobLauncher(JobRepository jobRepository) throws Exception {
        SimpleJobLauncher jobLauncher = new SimpleJobLauncher();
        jobLauncher.setJobRepository(jobRepository);
        return jobLauncher;
    }

}

@Configuration
public class ImportJobConfig {

    @Bean
    public FlatFileItemReader<Person> importReader(@Value("#{jobParameters[fullPathFileName]}") String pathToFile) {
        FlatFileItemReader<Person> reader = new FlatFileItemReader<>();
        reader.setResource(new FileSystemResource(pathToFile));
        reader.setLineMapper(new DefaultLineMapper<Person>() {{
            setLineTokenizer(new DelimitedLineTokenizer() {{
                setNames(new String[]{"firstName", "lastName"});
            }});
            setFieldSetMapper(new BeanWrapperFieldSetMapper<Person>() {{
                setTargetType(Person.class);
            }});
        }});
        return reader;
    }

    @Bean
    public PersonItemProcessor processor() {
        return new PersonItemProcessor();
    }

    @Bean
    public JdbcBatchItemWriter<Person> writer() {
        JdbcBatchItemWriter<Person> writer = new JdbcBatchItemWriter<>();
        writer.setItemSqlParameterSourceProvider(
                new BeanPropertyItemSqlParameterSourceProvider<Person>());
        writer.setSql("INSERT INTO people (first_name, last_name) VALUES (:firstName, :lastName)");
        writer.setDataSource(dataSource);
        return writer;
    }
    // end::readerwriterprocessor[]

    // tag::jobstep[]
    @Bean
    public Job importUserJob(JobCompletionNotificationListener listener) {
        return jobBuilderFactory.get("importUserJob").incrementer(new RunIdIncrementer())
                .listener(listener).flow(step1()).end().build();
    }

    @Bean
    public Step step1(@Qualifier("importReader") ItemReader<Person> importReader) {
        return stepBuilderFactory.get("step1").<Person, Person>chunk(10).reader(importReader)
                .processor(processor()).writer(writer()).build();
    }

}

@RestController
public class MyImportController {

    @Autowired private JobLauncher jobLauncher;
    @Autowired private Job importUserJob;

    @RequestMapping(value="/import/file", method=RequestMethod.POST)
    public String create(@RequestParam("file") MultipartFile multipartFile) throws IOException{

        //Save multipartFile file in a temporary physical folder
        String path = new ClassPathResource("tmpuploads/").getURL().getPath();//it's assumed you have a folder called tmpuploads in the resources folder
        File fileToImport = new File(path + multipartFile.getOriginalFilename());
        OutputStream outputStream = new FileOutputStream(fileToImport);
        IOUtils.copy(multipartFile.getInputStream(), outputStream);
        outputStream.flush();
        outputStream.close();       

        //Launch the Batch Job
        JobExecution jobExecution = jobLauncher.run(importUserJob, new JobParametersBuilder()
                .addString("fullPathFileName", fileToImport.getAbsolutePath())
                .toJobParameters());        

        return "OK";
    }

}
 类似资料:
  • 问题内容: 我的项目有此要求,即用户上传一个CSV文件,该文件必须被推送到mysql数据库。我知道我们可以使用Spring批处理来处理大量记录。但是我找不到适合我的这一要求的任何教程/示例代码。我遇到的所有教程都只是将CSV文件名硬编码为如下所示: https://spring.io/guides/gs/batch- processing/ 我需要使用用户上传的文件并进行相应处理。在这里的任何帮助

  • 我需要用CSV文件填充几个表。我试图使用一个循环,每一行都插入,但是一个有65,000条记录的文件需要我20分钟以上。 我想使用MySQL命令,但是我收到了这个消息: 第112行C:\xampp\htdocs\myProject\apps\backend\modules\member\actions\actions.class.php中禁止加载数据本地填充 经过一点研究,我了解到需要将PDO的一个

  • 问题内容: 我有一些要导入mySQL的CSV数据文件。我想在shell脚本中进行插入,以便可以将其自动化。但是,我对在脚本中使用明文形式输入用户名和密码感到有些厌倦 我有以下问题: 我对脚本中明文中的uname / pwd的想法感到不满意(反正还是这样,还是我太偏执)?也许我可以为插入表设置仅具有INSERT特权的用户? 数据库表(导入原始数据的数据库表)具有基于表列的唯一键。我尝试导入的数据中也

  • 我在360个CSV文件中有大量的数据,我想通过使用C#将它们存储在SQL Server数据库中。 我已经安装了Visual Studio 2010,但没有安装任何版本的SQL Server。 现在我有两个问题: 是否可以使用C#创建SQL Server数据库(尽管SQL Server不可用)? 如果是,如何创建数据库并使用C#将数据插入数据库? 我尝试了一些代码,如下所示,从不同的来源找到(盲目复

  • 想要知道更多东西吗?当你需要从表中查找某些值时,可以使用冗长的 case 语句或 selectors 实现,但更整洁的方式是使用 extlookup 函数实现。 在 puppetmaster 上可以使用 extlookup 函数查询外部的 CSV 文件,并返回匹配的数据片段。 将所有数据组织到一个单一的文件并将它从 Puppet 配置清单中分离出来, 可以使维护工作变得更简单,也便于与其他人分享:

  • 我有一个csv文件中的100个URL列表。第一列中的每一行都有一个url。我想加载每个url并从每个url中提取一段数据。 目前,我可以使用beautifulsoup和以下代码手动加载单个页面,以获取“Type”并将其保存到csv文件中: 但是,如果我想从csv文件中获取url列表,然后用代码解析每个url,并将每个“类型”保存到新csv文件中的单独一行,我不知道从何处开始。有什么想法吗? 尝试以