当前位置:   article > 正文

PostgreSQL的SQL语句参数上限 An I/O error occurred while sending to the backend_org.postgresql.util.psqlexception: an i/o error oc

org.postgresql.util.psqlexception: an i/o error occurred while sending to th

Mybatis后台批量插入数据报错:

数据库我用postgreSQL,持久成框架mybatis
现在有一个操作,需要将一大批数据(3000+)插入数据库,后台直接报错,报错原因如下:

  1. org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
  2. Caused by: java.io.IOException: Tried to send an out-of-range integer as a 2-byte value: 50805

原因:批量插入的顶峰在JDBC-Driver出现天花板.
简单来说就是SQL语句参数上限

可能我们首先想到的解决办法是分段批量插入,将sql语句分成几次执行,比如现在有3500条数据,一次性最多插入1500,分为3次插入;那代码怎么实现呢?
下面介绍2种解决方法,2种方法都用了递归算法;(当时的情况我这边一次性可以插入1800条,具体要看数据表中有多少字段)

注:以下方法可以写在service的通用方法中(如果有的话),这样所有实体类的service都可以调用。

第一种方法:

这是我的第一次尝试,虽然不太灵活,但能用,记录一下;后来才有第二种方法;

直接用java.util.List包提供的方法subList(int fromIndex, int toIndex);
subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段,可以理解为截取一个集合中的部分元素,他的返回值也是一个List。方法中的2个参数可以看成是数组的下标;代码如下:

  1. /**
  2. * 递归插入
  3. * @author: fangzf
  4. * @param: @param all 需要批量插入的集合
  5. * @param: @param strart 开始的下标
  6. * @param: @param end 结束的下标(包头不包尾)
  7. */
  8. public void add (List<T> all,int strart, int end){
  9. if(all.size()<=end){
  10. end = all.size();
  11. }
  12. //截取strart ~ end条数据
  13. List<T> collect = all.subList(strart, end);
  14. if(CollUtil.isEmpty(collect)){
  15. return;
  16. }
  17. //批量插入数据的方法(这里是通用的批量插入数据方法)
  18. insertList(collect);
  19. //递归 每次插入1500条数据,这里1500写死了,就是不灵活的地方
  20. //可以再传一个参数过来,这样会比较灵活
  21. add(all,strart+1500,end+1500);
  22. }
  23. //调用批量插入的方法 all表示业务中要插入的数据数组
  24. add(all,0,1500);

关于subList方法需要谨慎使用

在《阿里巴巴Java开发手册》中有提到subList方法需要谨慎使用,具体可以看一下这篇文章:
为什么阿里巴巴要求谨慎使用ArrayList中的subList方法:原创 | 为什么阿里巴巴要求谨慎使用ArrayList中的subList方法 - 好文 - 码工具

第二种方法:(推荐)
说到数组的操作我们肯定会想起java8提供强大的lambda表达式(链接到lambda表示文章),这里要用到skip和limit方法;

skip(n):跳过元素,返回一个扔掉前 n 个元素的流。若流中元素不足 n 个,则返回一个空流。

limit(n):截断流,使其元素不超过给定数量。

代码如下:

  1. //递归插入
  2. public void add (List<Dormitory> all,long strart,long limit){
  3. //截取 从strart开始截取 截取limit条
  4. List<Dormitory> collect = all.stream().skip(strart).limit(limit).collect(Collectors.toList());
  5. if(CollUtil.isEmpty(collect)){
  6. return;
  7. }
  8. //批量插入数据的方法
  9. insertList(collect);
  10. //递归 每次插入limit条数据
  11. add(all,strart+limit,limit);
  12. }
  13. //调用批量插入的方法 all表示业务中要插入的数据数组
  14. add(all,0L,1500L);

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/你好赵伟/article/detail/483651
推荐阅读
相关标签
  

闽ICP备14008679号