在使用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. [LOJ3046][ZJOI2019]语言:树链的并+线段树合并

    分析 问题显然可以转化为对于每个节点询问所有这个节点的所有链的链并的大小. 考场上我直接通过树剖打标记+树剖线段树维护以\(O(n \log^3 n)\)的时间复杂度暴力实现了这个过程.(使用LCT或 ...

  2. 分治NTT:我 卷 我 自 己

    感觉这种东西每次重推一遍怪麻烦的,就写在这里了. 说白了就是根据分治区间左端点是否为\(0\)分类讨论一下,一般是如果不是\(0\)就要乘\(2\),不过还是需要具体问题具体分析一下才好(就比如下面的 ...

  3. 【转】HDU-6035-Colorful Tree

    转自http://blog.csdn.net/Bahuia/article/details/76141574 题意: 题目链接:http://acm.hdu.edu.cn/showproblem.ph ...

  4. WebView内置方案主要是通过重写WebChromeClient 来实现的,如下面的代码所示。

    基本思想也很简单:通过WebChromeClient的方法以startActivityForResult的方式打开系统的文件选择器,选择文件后在onActivityResult中将结果回传给Webvi ...

  5. leetcode 102二叉树的层序遍历

    5月20更新: 使用借助队列实现bfs,定义len记录队列的尺寸直接进行遍历层序 /** * Definition for a binary tree node. * struct TreeNode ...

  6. DateTimePicker 日期时间选择器

    在同一个选择器里选择日期和时间 DateTimePicker 由 DatePicker 和 TimePicker 派生,Picker Options 或者其他选项可以参照 DatePicker 和 T ...

  7. TCP/IP,Http,Socket的区别

    大学学习网络基础的时候老师讲过,网络由下往上分为物理层.数据链路层.网络层.传输层.会话层.表示层和应用层.通过初步的了解,我知道IP协议对应于网络层,TCP协议对应于传输层,而HTTP协议对应于应用 ...

  8. java利用dom4j读取xml

    java连接oracle数据库的时候, 需要从特定地方读取xml文件中的sql去get结果集, xml文件放在和java文件: SqlLoaderFromXML的目录下OracleSQL, xml文件 ...

  9. linux 下载jdk 、maven、git

    jdk: wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-secureback ...

  10. JavaScript日常学习6

    JavaScript的运算符.比较符.条件语句.循环语句.跳出循环(break.continue).标签 JavaScript的运算符.比较符.条件语句.循环语句.跳出循环(break.continu ...