在使用JPA的仓储repository进行查询时,经常用到findAllbyId的方法: repository.findAllbyId()

但如果像下面的代码,当list的size量太大的话,就会报栈溢出的的错误:java.lang.StackOverflowError

@RequestMapping("/stackOverFlow")
public Integer stackOverFlow() { List<String> ids = new ArrayList<>();
for (int i = 0; i < 5000; i++) {
ids.add("123123123123");
}
List<BillDO> allById = dwBillRepository.findAllById(ids); return allById.size();
}

报错信息如下:

Caused by: java.lang.StackOverflowError
at antlr.BaseAST.toString(BaseAST.java:333) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:341) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]
at antlr.BaseAST.toStringList(BaseAST.java:347) ~[antlr-2.7.7.jar:?]

原因就是在拼sql时方法入栈太深,超过了jvm允许的最大深度,也就是递归调用的太深了。

public String toStringList() {
String var2 = "";
if (this.getFirstChild() != null) {
var2 = var2 + " (";
} var2 = var2 + " " + this.toString();
if (this.getFirstChild() != null) {
var2 = var2 + ((BaseAST)this.getFirstChild()).toStringList();
} if (this.getFirstChild() != null) {
var2 = var2 + " )";
} if (this.getNextSibling() != null) {
var2 = var2 + ((BaseAST)this.getNextSibling()).toStringList();
} return var2;
}

解决方法就是不要递归的太深。或者调整JVM参数栈大小默认为1m,可以调整到10m,看看不能解决问题,但这样做不推荐。会影响线程数,从而影响系统性能。

具体到上面的问题就是一次不要查太多的数据。如果in的数量有5000,我们就分开查询一次只查1000,查5次。再把结果组合在一起。

如果每个业务都单独写的话,就太麻烦了,可以写个公共的方法,如下: JPA_QUERY_LIST_MAX_SIZE是一个常量数据值,如1000个查一次。这里使用了并行查询,查询效率更高。

public <T> List<T> findAll(List<String> ids, Function<List<String>, List<T>> func) {

        List<List<String>> idGroups = Lists.partition(ids, JPA_QUERY_LIST_MAX_SIZE);
        ThreadPoolExecutor executor = (ThreadPoolExecutor) Executors.newFixedThreadPool(idGroups.size());
executor.setKeepAliveTime(10, TimeUnit.SECONDS);//解决线程不退出的问题
executor.allowCoreThreadTimeOut(true);

return idGroups
.stream()
.collect(ParallelCollectors
.parallelToList(i -> func.apply(i), executor, idGroups.size()))
.join()
.stream()
.flatMap(Collection::stream)
.collect(toList());
}

以上代码利用如一个第三方的库:需要引用:

<dependency>
<groupId>com.pivovarit</groupId>
<artifactId>parallel-collectors</artifactId>
<version>1.1.0</version>
</dependency>

这里引出一个题外话,如果in查询数据量很大的话,可能会导致索引失效的问题。需要重点看一下。

java.lang.StackOverflowError解决的更多相关文章

  1. java.lang.StackOverflowError 解决方法

    ♦ java.lang.StackOverflowError : 由于深度递归,抛出此错误以指示应用程序的堆栈已耗尽. 在递归中,一个方法在执行期间调用自己.递归被认为是一种强大的通用编程技术,但必须 ...

  2. java.lang.StackOverflowError 解决办法

    java.lang.StackOverflowError com.sxt.servlet.servlet1.LoginServlet.doGet(LoginServlet.java:15) com.s ...

  3. Spark出现java.lang.stackoverflowerror的解决方法

    正在测试的程序需要多次迭代(400+次),每次迭代有复杂的运算 迭代到100多次的时候报java.lang.stackoverflowerror的错误 解决方法:先checkpoint()再count ...

  4. struts2 java.lang.StackOverflowError org.apache.struts2.json.JSONWriter

    1. 问题描述: 页面通过异步访问action,    action的方法通过map封装数据,struts的result的type设置为json,后台报错 六月 25, 2016 6:54:33 下午 ...

  5. android布局太深导致的 java.lang.StackOverflowError

    E/AndroidRuntime( 1900): java.lang.StackOverflowError E/AndroidRuntime( 1900):     at android.graphi ...

  6. 【转】java.lang.StackOverflowError

    http://blog.csdn.net/g19920917/article/details/8765638 出现一个java.lang.StackOverflowError异常.弄了半天,又是问高手 ...

  7. servlet运行“/*”引起的java.lang.StackOverflowError

    <servlet> <servlet-name>login</servlet-name> <servlet-class>com.jd.login.UI. ...

  8. Java EE之Hibernate异常总结【5】java.lang.StackOverflowError[栈溢出]

    Exception in thread "main" java.lang.StackOverflowError at java.lang.reflect.InvocationTar ...

  9. android java.lang.StackOverflowError

    转自:http://hi.baidu.com/424660053/item/bee53a2633870dccddf69a17 最近做项目出现一个java.lang.StackOverflowError ...

随机推荐

  1. HTML jQuery 文档操作 - html() 方法

    jQuery 文档操作 - html() 方法 jQuery 文档操作参考手册 实例 设置所有 p 元素的内容: $(".btn1").click(function(){ $(&q ...

  2. Java使用阿里云OSS对象存储上传图片

    原 Java使用阿里云OSS对象存储上传图片 2017年03月27日 10:47:28 陌上桑花开花 阅读数 26804更多 分类专栏: 工作案例总结 版权声明:本文为博主原创文章,遵循CC 4.0 ...

  3. 分布式-信息方式-ActiveMQ的Message dispatch高级特性之(指针) Message cursors

    Message dispatch高级特性之 Message cursors概述            ActiveMQ发送持久消息的典型处现方式是:当消息的消费者准备就绪时,消息发送系统把存储的 消息 ...

  4. Java常考面试题整理(一)

    1.什么是java虚拟机?为什么java被称作是"平台无关的编程语言". 参考答案: java虚拟级是一个可以执行java字节码的虚拟机进程,java源文件被编译成能被java虚拟 ...

  5. 第八周学习总结&实验报告(6)

    实验六 异常 一.实验目的: (1)理解异常的基本概念: (2)掌握异常处理方法及熟悉常见异常的捕获方法. 二.实验要求: (1)练习捕获异常.声明异常.抛出异常的方法.熟悉try和catch子句的使 ...

  6. VSCode安装go语言开发环境,go插件问题解决

    在安装go插件时,会自动更新很多依赖库文件,都是从Github更新下来,但是因为Github的文件中,多有应用go官网中的文件,导致,因为网络缘故,不能直接下载,导致安装失败,如下:   Instal ...

  7. leetcode-easy-string-28 Implement strStr()

    mycode   77.15% class Solution(object): def strStr(self, haystack, needle): """ :type ...

  8. leetcode 118. Pascal's Triangle 、119. Pascal's Triangle II 、120. Triangle

    118. Pascal's Triangle 第一种解法:比较麻烦 https://leetcode.com/problems/pascals-triangle/discuss/166279/cpp- ...

  9. logistic regression中的cost function选择

    一般的线性回归使用的cost function为: 但由于logistic function: 本身非凸函数(convex function), 如果直接使用线性回归的cost function的话, ...

  10. rocketMQ 订阅关系

    场景:2 个消费者进程中,创建了 2 个消费者,同属于 1 个消费组,但是订阅了不同的 topic,会因为订阅信息相互覆盖,导致拉不到消息. 原因是 rocketMQ 的订阅关系,是根据 group ...