EasyExcel是什么?
EasyExcel是一个基于Java的简单、省内存的读写Excel的开源项目。在尽可能节约内存的情况下支持读写百M的Excel。
github地址
## 1.1新建一个Module,在pom文件添加需要的依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.58</version>
<scope>test</scope>
</dependency>
<!--Alibaba-EasyExcel-->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.1.1</version>
</dependency>
<!--单元测试-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
<!--mybatis-spring集成依赖-->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aspects</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.5.RELEASE</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.1</version>
</dependency>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.20</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.8</version>
<scope>compile</scope>
</dependency>
1.2、设计与excel对应的表
CREATE TABLE `user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(11) DEFAULT NULL,
`birthday` date DEFAULT NULL,
`sex` varchar(3) DEFAULT NULL,
`email` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1.3在resources目录下创建jdbc.properties,设置jdbc连接数据库的参数
jdbc.url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=UTC
jdbc.username=root
jdbc.password=abc123
1.4在resources目录下创建applicationContext.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">
<!--把数据库的配置信息写在独立的文件,便于修改数据库的配置内容
-->
<context:property-placeholder location="classpath:jdbc.properties"/>
<!--声明数据源dataSource,作用连接数据库-->
<bean id="myDataSource" class="com.alibaba.druid.pool.DruidDataSource"
init-method="init" destroy-method="close">
<!--使用属性配置文件中的数据,语法${key}-->
<property name="url" value="${jdbc.url}"/>
<property name="username" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
</bean>
<!--声明是mybatis中提供的sqlsession-->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<!--set注入,把数据库连接池付给了datasource属性-->
<property name="dataSource" ref="myDataSource"/>
<!--mybatis主配置文件的位置
configLocation的属性是resource类型,读取配置文件的
的赋值时使用value ,classpath:文件位置
-->
<property name="configLocation" value="classpath:mybatis.xml"/>
</bean>
<!--创建dao对象使用SQL session的getmapper
在内部调用getmapeer生成每个到接口的代理对象
-->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<!--指定SQL sessionfactory对象的id-->
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/>
<!--指定包名包名是dao接口所在的包名
MapperScannerConfigurer会扫描包中接口的所有接口,把每个接口都执行
一次getmapper方法得到每个dao接口的对象,创建好的对象放到spring容器里
-->
<property name="basePackage" value="你的dao接口所在的包名"/>
</bean>
</beans>
import com.alibaba.excel.annotation.ExcelProperty;
import com.alibaba.excel.annotation.format.DateTimeFormat;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import java.util.Date;
@Getter
@Setter
@ToString
@NoArgsConstructor
public class DemoData {
/**
* 用名字去匹配,这里需要注意,如果名字重复,会导致只有一个字段读取到数据
*/
@ExcelProperty("id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ExcelProperty("姓名")
private String name;
@ExcelProperty("生日")
@DateTimeFormat("yyyy-MM-dd")
private Date birthday;
@ExcelProperty("性别")
private String sex;
@ExcelProperty("邮箱")
private String email;
}
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public interface DemoDAO {
//保存数据到数据库的方法
int save(DemoData demoData);
}
3.1在同目录下创建DemoDAO.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="DemoDAO的绝对路径">
<insert id="save">
insert into user values (#{id},#{name},#{birthday},#{sex},#{email})
</insert>
</mapper>
public interface ExcelService {
int addUser(DemoData demoData);
}
4.1、实现ExcelService接口,并重写方法操作DAO
import java.util.List;
public class ExcelServiceImpl implements ExcelService {
private DemoDAO demoDAO;
public void setDemoDAO(DemoDAO demoDAO) {
this.demoDAO = demoDAO;
}
@Override
public int addUser(DemoData demoData) {
int nums = demoDAO.save(demoData);
return nums;
}
}
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.ArrayList;
import java.util.List;
public class DemoDataListener extends AnalysisEventListener<DemoData> {
/**
* 每隔10条存储数据库,实际使用中可以3000条,然后清理list ,方便内存回收
*/
private static final int BATCH_COUNT = 10;
List<DemoData> list = new ArrayList<>();
/**
* 这个每一条数据解析都会来调用
*/
@Override
public void invoke(DemoData data, AnalysisContext context) {
System.out.println("解析到一条数据:"+data);
list.add(data);
// 达到BATCH_COUNT了,需要去存储一次数据库,防止数据几万条数据在内存,容易OOM
if (list.size() >= BATCH_COUNT) {
saveData();
// 存储完成清理 list
list.clear();
}
}
/**
* 所有数据解析完成了 都会来调用
*
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// 这里也要保存数据,确保最后遗留的数据也存储到数据库
saveData();
System.out.println("所有数据解析完成!");
}
/**
* 加上存储数据库
*/
private void saveData() {
String config = "applicationContext.xml";
ApplicationContext ac = new ClassPathXmlApplicationContext(config);
ExcelService demodataService = (ExcelService) ac.getBean("demodataService");
System.out.println("{}条数据,开始存储数据库!"+ list.size());
for (DemoData demoData : list) {
System.out.println("list里的:"+demoData);
demodataService.addUser(demoData);
}
System.out.println("存储数据库成功!");
}
}
5.1、回到applicationContext.xml添加bean标签声明Service
<!--声明service-->
<bean id="demodataService" class="ExcelServiceImpl的全限定名称">
<property name="demoDAO" ref="demoDAO"/>
</bean>
public class Readtest {
@Test
public void readTest() {
// 有个很重要的点 DemoDataListener 不能被spring管理,要每次读取excel都要new,然后里面用到spring可以构造方法传进去
String fileName ="excel文件地址";
// 这里 需要指定读用哪个class去读,然后读取第一个sheet 文件流会自动关闭
EasyExcel.read(fileName, DemoData.class, new DemoDataListener()).sheet().doRead();
}
}