问题一:在easyexcel中读取excel文件并持久化到数据库 , 我们如果在监听器中的invoke()方法中直接调用mapper层的保存方法将数据保存到数据库的话会出现一个问题 , 那就是有多少条数据我们就需要操作数据库执行多少次保存方法 , 这样的话会导致我们的保存效率很差
解决方式是:我们在监听器中新增一个数据列表用于保存easyexcel从excel文件中读取的数据 , 然后我们批量进行导入
问题二:但是这样我们就又存在另外一个问题 , 那就是我们的数据量如果特别大了 , 我们全部保存到list中 , 一次性批量导入 , 数据库也不接受 , 也就是说批量导入数据库是有数据量限制的
解决方式:我们进行分批导入数据 , 每一批次导入一部分 , 那怎么实现呢 , 我们可以设置一个静态常量用于保存每多少条数据我们进行一次保存操作
但是这样我们就出现了问题三:我们假如设置每五条数据进行一次保存 , 以上的代码就是当list数据量达到五条时 , 他就会调用保存到数据库的方法 , 然后清空list , 每次这样进行。但是假如我们有13条数据 , 前10条我们都保存了 , 但是第三轮时 , list.size()也达不到五条 , 所以第三轮剩下的三条数据压根不会进行if条件判中的保存到数据库的方法 , 也不会清除list。这怎么办呢?
解决方式:幸好我们的监听器中还提供了一个方法 , 那就是
doAfterAllAnalysed()
方法 , 这个方法会在easyexcel读取完文件中所有数据后执行 , 在这个方法中我们再次调用save方法把剩下的数据批量保存到数据库中就可以了。
接下来我们又遇到了问题四:我们一直说在监听器这个方法中调用mapper层的save方法批量保存数据到数据库 , 但是这个监听器他不归spring管理呀 , 他的类上也没有加让标识spring的注解 , 那他怎么进行mapper注入呢 , 如何能拿到mapper对象呢?
解决方式:我们这个监听器是在哪儿里用的呢?监听器是在service中被new的
EasyExcel.read(inputStream , ExcelDictDTO.class , new ExcelDictDTOListener(baseMapper)).sheet().doRead();
, service是归spring管理的 , 所以我们可以在这里new的时候调用监听器的构造函数将mapper对象传入监听器中 , 这样监听器中就可以调用mapper对象进行数据的批量保存了。
我们在以上截图中发现了service层竟然有一个注解叫做 @Transactional(rollbackFor = {Exception.class})
, 我这里加这个注解的原因是使用事务 , 为的是 批量插入的时候如果出现异常 , 我们希望它能够回滚 , 因为如果不回滚的话我们一旦中途出错 , 我们重新导入时候需要将之前导入的全部删除 , 及其耗费时间和性能。‘
以上的问题我们都解决了 , 理论上应该没问题了 , 但是我们进行文件上传保存时候 , 发现还是报错了 , 如下是错误信息
我们可以发现这个错误是
Invalid bound statement (not found)
这个问题通常来说是 有以下的原因:
- xml中数据不存在
- xml中的id 或者 namespace 没有和接口的全类名或者方法名对应上
- xml文件位置存在问题
前两种我们就根据问题查看自己的配置是否正确就可以了
我们来说说第三种问题:
xml在mybatis中默认的位置实在resources/xml下面的任意xml文件或者任意目录下的xml文件 , 很显然我们的项目中将xml放置在java目录下和mapper接口放在了一起 , 那这样我们该怎么办呢?
第一种解决方式就是将xml文件移动到我们的resources/xml目录下面 , 但是我们就是不想修改xml文件位置我们该怎么办呢
在springboot中我们可以在yml启动配置文件中进行mapper配置
mapper-locations: classpath:com/starcpdk/borrow/core/mapper/xml/*.xml
这个就是配置xml文件位置的 , 但是我们在项目中配置了 , 发现还是会报
Invalid bound statement (not found)
这个错 , 那是为什么呢?
我们发现在target导出目录中没看到xml文件 , 这是什么情况呀 ,原因如下 , 我们的maven环境下默认导出的是resource下的 , 所以我们那么配置相当于识别到的是 resources/com/starcpdk/borrow/core/mapper/xml/*.xml
那么怎么办呢?
我们需要在maven的配置文件 pom.xml中添加如下的节点进行java目录下的xml资源导出
<build>
<!-- 项目打包时会将java目录中的*.xml文件也进行打包 -->
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.xml</include>
</includes>
<filtering>false</filtering>
</resource>
</resources>
</build>