如何从 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<User>
声明为控制器方法的输入,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 文件中读取数据并将其存储在数据库中?弹簧靴的主要内容,如果未能解决你的问题,请参考以下文章
如何从 zip 文件夹中的 csv 文件中读取数据并将 csv 文件中的数据保存在数据库中?
如何从 SQL Server 表中读取图像数据(存储 word 文档)并将其保存到本地文件夹
如何读取从 API 检索到的 JSON 并将其保存到 CSV 文件中?