流程

依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<!--web项目-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!--方便标注实体类-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
</dependency>
<!--json转换-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.78</version>
</dependency>
<!--使用swagger方便调试-->
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
<!--EasyExcel操作Excel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.0.3</version>
</dependency>
<!--mysql数据库连接驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--使用mybatis-plus操作数据库-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.1</version>
</dependency>

结构

搭建

1、配置数据库连接信息

1
2
3
4
5
6
spring:
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/core?useUnicode=true&characterEncoding=utf8
username: root
password: 123456

2、建立实体类对象

根据 Excel 表建立对应接收的实体类对象

UserExcel 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@Data
public class UserExcel {
/**
* 用户名
* 对应Excel表格第0列
*/
@ExcelProperty(index = 0)
private String username;

/**
* 密码
* 对应Excel表格第1列
*/
@ExcelProperty(index = 1)
private String password;

/**
* 年龄
* 对应Excel表格第2列
*/
@ExcelProperty(index = 2)
private Integer age;
}

根据数据库字段建立对应的实体类对象

User 如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
@Data
public class User {

/**
* 用户id
* 使用MybatisPlus时设置数据库自增id
* 需要数据库对应表也设置了自动递增
*/
@TableId(type = IdType.AUTO)
private Integer userId;

/**
* 用户名
*/
private String username;

/**
* 密码
*/
private String password;

/**
* 年龄
*/
private Integer age;

/**
* 爱好
*/
private String habbit;
}

3、mapper

1
2
3
public interface UserMapper extends BaseMapper<User> {

}

4、service

创建 UserService 接口,继承 IService

1
2
3
4
5
6
7
8
9
10
public interface UserService extends IService<User> {

/**
* 保存前端传来的excel文件中的数据
*
* @param file 上传的excel文件
*/
void saveByExcel(MultipartFile file);

}

实现类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

@Resource
private UserService userService;


/**
* 保存前端传来的excel文件中的数据
*
* @param file 上传的excel文件
*/
@Override
public void saveByExcel(MultipartFile file) {
try {
//文件输入流
InputStream in = file.getInputStream();
// 参数:要读取的文件、标有注释了配置信息的类、读取监听器
EasyExcel.read(in, UserExcel.class, new ExcelDataListener(userService)).sheet().doRead();
} catch (Exception e) {
e.printStackTrace();
}
}
}

5、创建 Excel 监听类

按照官网的注释,监听类不能被 spring 管理,每次读取 excel 都要 new,然后监听类里面用到 spring 可以通过构造方法传进去

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
@Slf4j
public class ExcelDataListener extends AnalysisEventListener<UserExcel> {

/**
* 因为监听对象需要我们自己new,因此不能交给spring容器进行管理
* 想要在该监听类中调用service的方法,需要手动传入service对象
*/
private UserService userService;

/**
* 每次创建Listener的时候
* 手动传入spring管理的类传进来
*
* @param userService
*/
public ExcelDataListener(UserService userService) {
this.userService = userService;
}


/**
* 每一条数据解析都会来调用
*
* @param data
* @param context
*/
@Override
public void invoke(UserExcel data, AnalysisContext context) {
log.info("解析到一条数据:{}", JSON.toJSONString(data));

// 获取到Excel中每一行的数据后,补充完整user对象
User user = new User();
user.setUsername(data.getUsername());
user.setPassword(data.getPassword());
user.setAge(data.getAge());
user.setHabbit("读书");

// 使用 mybatis-plus 自带的 save() 方法
// 将填充好的对象保存到数据库中
userService.save(user);
}

/**
* 所有数据解析完成后
* 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
log.info("所有数据解析完成!");
}
}

6、controller

1
2
3
4
5
6
7
8
9
10
11
12
13
14
@Api(tags = "将Excel保存到数据库")
@RestController
@RequestMapping("/excel")
public class ExcelController {

@Resource
private UserService userService;

@PostMapping("/save")
public String save(MultipartFile file) {
userService.saveByExcel(file);
return "success";
}
}

7、启动类标上注解

1
2
3
4
5
6
7
8
9
10
11
12
13
/**
* 启用Swagger2
* 包扫描
*/
@SpringBootApplication
@EnableSwagger2
@MapperScan("com.shiguang.excel.mapper")
public class ExcelApplication {

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

测试

访问默认端口: http://localhost:8080/swagger-ui.html

效果

优化

  • 可以考虑使用 list 集合存储读取到每行的 Excel 数据,达到一个数量批量添加到数据库中,减少数据库的访问

关于 Mybatis Plus 的@TableId 注解

这个注解主要用于对应数据库表的实体类中的主键属性。

字段说明
value映射主键字段的名字
type设置主键类型、如果数据库主键设置了自增建议使用“AUTO”

其中 type 有六种类型,后三种只有插入主键为空时,才会自动填充

type说明
IdType.AUTO数据库自增 ID(需要数据库设置对应字段的自动递增)
IdType.ASSIGN_ID如果不设置类型值,默认策略(自 3.3.0 起)。该策略会使用雪花算法自动生成主键 ID,主键类型为长或字符串(分别对应的 MySQL 的表字段为 BIGINT 和 VARCHAR)
IdType.ASSIGN_UUID主键类型为 String,对应 MySQL 的表分段为 VARCHAR
IdType.INPUT必须手动输入,数据库设置了自增也没用
IdType.NONE数据库未设置主键类型,将会跟随全局(全局的主键策略如果没有设置,默认是雪花算法)

变量策略配置

如果希望全部使用 AUTO 策略,可以在 application.yml 中添加以下配置:

1
2
3
4
mybatis-plus:
global-config:
db-config:
id-type: auto