概念
-
监听器
- 帮助我们获取到excel中每一行的数据,并循环调用invoke方法去获得每一行的数据
- 数据异常时定位到具体的行和列
- 批量导入,控制内存中数据量,达到一定量就导入到数据库(这篇没有用到批量导入)
思路
在开发中我们需要将excel中的数据和数据库中的数据进行比对,如果一样,不进行操作,不一样更新数据库
代码
package cn.testin.Listener;
import cn.testin.api.cfg.bean.AdditionalConfig;
import cn.testin.api.devicecontrol.DeviceAssetsApi;
import cn.testin.common.pojo.GeneralException;
import cn.testin.common.util.log.Logit;
import cn.testin.pojo.device.DeviceInfoExcel;
import com.alibaba.druid.util.StringUtils;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.excel.exception.ExcelDataConvertException;
public class DeviceInfoExcelListener extends AnalysisEventListener<DeviceInfoExcel> {
/**
* 因为SubjectExcelListener不能交给spring进行管理,需要自己new,不能注入其他对象,如果哦我们想要通过service层获得数据库的数据,我们就需要注入某个service(deviceAssetsApi,这个虽然不是service层,但是性质一样,都是从数据库获取数据)
*/
public DeviceAssetsApi deviceAssetsApi;
public DeviceInfoExcelListener(DeviceAssetsApi deviceAssetsApi){
this.deviceAssetsApi=deviceAssetsApi;
}
/**
* 通过 AnalysisContext 对象还可以获取当前 sheet,当前行等数据
* 读取excel内容,一行一行进行读取,会循环调用
*/
@Override
public void invoke(DeviceInfoExcel deviceInfoExcel, AnalysisContext analysisContext) {
// 取到更改过的数据
DeviceInfoExcel deviceInfoExcels = savaAssetsInfo(deviceInfoExcel);
// 如果有数据,更新最新资产信息和增加资产信息记录
if(deviceInfoExcels != null) {
try {
//数据库更新数据
deviceAssetsApi.update();
} catch (Exception e) {
Logit.errorLog(e.getMessage(), new Throwable(e));
}
}
}
/**
* 判断数据是否没有改变,取到更改过的数据
*/
private DeviceInfoExcel savaAssetsInfo(DeviceInfoExcel deviceInfoExcel) {
try{
// 获取到原来数据库中单个用户信息
DeviceInfoExcel assetInfoExcel= deviceAssetsApi.getAssetInfo(deviceInfoExcel.getDeviceid());
// 数据库信息和excel信息比对
if (StringUtils.equalsIgnoreCase(assetInfoExcel.getDeviceid(), deviceInfoExcel.getDeviceid())) {
if (assetInfoExcel.equals(deviceInfoExcel)) {
// 数据一样,不操作
return null;
} else {
// 数据不一样,更新
return deviceInfoExcel;
}
}
} catch (GeneralException e) {
Logit.errorLog(e.getMessage(), new Throwable());
}
return null;
}
/**
* 所有数据解析完成了 都会来调用
*
* @param analysisContext
*/
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
/**
* 监听器实现这个方法就可以在读取数据的时候获取到异常信息Logit.errorLog
*/
@Override
public void onException(Exception exception, AnalysisContext context) {
Logit.errorLog("解析失败,但是继续解析下一行:", new Throwable(exception.getMessage()));
// 如果是某一个单元格的转换异常 能获取到具体行和列
if (exception instanceof ExcelDataConvertException) {
ExcelDataConvertException excelDataConvertException = (ExcelDataConvertException)exception;
Logit.errorLog("错误在这行:", new Throwable(String.valueOf(excelDataConvertException.getRowIndex())));
Logit.errorLog("错误在这列:", new Throwable(String.valueOf(excelDataConvertException.getColumnIndex())));
}
}
}
这里我们重写了DeviceInfoExcel的equals方法,来对比两个对象中的值是否相同
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
DeviceInfoExcel that = (DeviceInfoExcel) o;
return Objects.equals(deviceid, that.deviceid) &&
Objects.equals(brandName, that.brandName) &&
Objects.equals(modelName, that.modelName) &&
Objects.equals(assetsNum, that.assetsNum) &&
Objects.equals(owner, that.owner) &&
Objects.equals(descr, that.descr) &&
Objects.equals(operator, that.operator) &&
Objects.equals(region, that.region) &&
Objects.equals(additionalConfig == null ? 0 : String.valueOf(additionalConfig.getPrice()), that.additionalConfig == null ? 0 : String.valueOf(that.getAdditionalConfig().getPrice()));
}