如何从 csv 文件中读取数据并将其存储在数据库中?弹簧靴

Posted

技术标签:

【中文标题】如何从 csv 文件中读取数据并将其存储在数据库中?弹簧靴【英文标题】:How to read data from csv file and store it in the database ? Spring Boot 【发布时间】:2018-12-01 21:03:20 【问题描述】:

例如,我有一个由用户名、电话号码和地址组成的用户实体。 我想从 csv 文件中读取所有这些字段并将其存储在数据库中的相应表中?

谁能帮我描述一下如何做到这一点?或者有没有关于如何做到这一点的文档?

【问题讨论】:

查看 spring-batch 做到了。但是他们在那里专门从一个文件中获取数据。我想打一个 api,允许用户从包含数据的系统中选择 csv 文件 【参考方案1】:

我假设您希望用户从某个 UI 上传文件。根据您构建 UI 的具体方式,您可能会:

发送多部分 HTTP POST 请求(mime 类型 = multipart/form-data;请参阅 What should a Multipart HTTP request with multiple files look like?) 发送一个简单的 POST 请求,正文直接包含文件内容。

使用 Spring 可以很容易地解决这两个问题。

假设我们有以下实体:

@Data
@Entity
public class User 
    @Id
    private String username;
    private String phoneNumber;
    private String address;

我们定义了一个用于访问数据库的 Spring Data 存储库:

public interface UserRepository extends JpaRepository<User, String> 


对于 CSV 反序列化,我建议使用 Jackson。 Spring Boot 已经自带 Jackson,但是我们需要在你的 pom 中为 CSV 添加数据格式扩展:

    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-csv</artifactId>
    </dependency>

这样,我们可以创建一个简单的实用方法,该方法知道读取给定 POJO 类的 CSV:

public class CsvUtils 
    private static final CsvMapper mapper = new CsvMapper();
    public static <T> List<T> read(Class<T> clazz, InputStream stream) throws IOException 
        CsvSchema schema = mapper.schemaFor(clazz).withHeader().withColumnReordering(true);
        ObjectReader reader = mapper.readerFor(clazz).with(schema);
        return reader.<T>readValues(stream).readAll();
    

然后我们创建一个简单的 Rest Controller 来处理上传:

@RestController
@RequiredArgsConstructor
public class UserController 
    private final UserRepository repository;

    @PostMapping(value = "/upload", consumes = "text/csv")
    public void uploadSimple(@RequestBody InputStream body) 
        repository.saveAll(CsvUtils.read(User.class, body));
    

    @PostMapping(value = "/upload", consumes = "multipart/form-data")
    public void uploadMultipart(@RequestParam("file") MultipartFile file) 
        repository.saveAll(CsvUtils.read(User.class, file.getInputStream()));
    

如果您还需要一些 html 来进行上传,以下 sn-p 是一个最小的工作示例:

<form action="/upload" method="post" enctype="multipart/form-data">
    <input type="file" name="file" id="file" />
    <input type="submit" name="submit" value="Submit" />
</form>

稍后编辑:如果您还想验证传入的数据,请首先使用javax.validation 约束来注释您的实体类属性。例如:

@Data
@Entity
class User 
    @Id
    @Email
    @NotEmpty
    private String username;
    @Pattern(regexp = "[0-9 ()-]4,12")
    private String phoneNumber;
    private String address;

然后您可以选择执行实际验证调用的位置:

    服务级别。这是我个人在这种情况下推荐的方法,因为它很容易设置并且会尽早执行验证。为此,您在控制器和存储库之间引入了一个简单的 @Service 类。
@Service
@Validated
@RequiredArgsConstructor
class UserService 
    private final UserRepository repository;
    public void saveAll(@Valid List<User> users) 
        repository.saveAll(users);
    

然后您将使用此服务类而不是控制器类中的存储库。

    存储库级别:在这里您实际上不需要执行任何操作。如果您使用验证约束对实体类进行注释,Hibernate 会自动在预插入侦听器 (BeanValidationEventListener) 中调用验证。

    控制器级别。这设置起来比较棘手。在自定义 HttpMessageConverter 中移动 CSV 反序列化。您还应该将此转换器添加到FormHttpMessageConverter(以便它可以使用它来反序列化多部分请求的一部分)。然后,理论上您可以将@Valid List&lt;User&gt; 声明为控制器方法的输入,Spring 会根据 mime 类型自动调用消息转换器,然后调用验证器。示例见Add JSON message converter for multipart/form-data。

最后,您可以随时手动调用验证:Manually call Spring Annotation Validation。

【讨论】:

如果我使用 gradle ,我应该使用哪个依赖项? Gradle 可以使用与 maven 完全相同的依赖项。例如,如果您搜索我为 maven 指定的依赖项,您会在 mvn 存储库 (mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/…) 中找到它,并且您必须包含 sn-p 以声明您对 Gradle 的依赖项:compile group: 'com.fasterxml.jackson.dataformat', name: 'jackson-dataformat-csv', version: '2.9.6'。如果你已经导入了 bom,我想你可以省略版本:docs.spring.io/spring-boot/docs/current/gradle-plugin/reference/… ***.com/questions/50998730/…。你能看看这个吗 你的 utils 示例中的“mapper”从何而来? 好收获!我编辑了答案以显示它是如何实例化的:CsvMapper mapper = new CsvMapper();.【参考方案2】:

您可以使用 openCSV 轻松实现这一目标。 对于已知的 POJO 用户,您只需将 CSV 列(在您的案例中为标题)映射到 POJO 中的相应字段。

只需将以下内容添加到您的依赖项中,但请检查您的应用程序的最新版本。

<dependency> 
<groupId>com.opencsv</groupId> 
<artifactId>opencsv</artifactId> 
<version>4.1</version> 
</dependency> 

此链接将引导您浏览https://www.geeksforgeeks.org/mapping-csv-to-javabeans-using-opencsv/

【讨论】:

以上是关于如何从 csv 文件中读取数据并将其存储在数据库中?弹簧靴的主要内容,如果未能解决你的问题,请参考以下文章

如何在 csv 文件中写入和附加数据并将其存储在列表中

如何从 zip 文件夹中的 csv 文件中读取数据并将 csv 文件中的数据保存在数据库中?

如何从 SQL Server 表中读取图像数据(存储 word 文档)并将其保存到本地文件夹

如何读取从 API 检索到的 JSON 并将其保存到 CSV 文件中?

如何在 Python 中将 Azure Blob 文件 CSV 转换为 Excel

如何逐个读取csv文件数据并将其放入变量Using Groovy