Search code examples
javaspringhibernatespring-data-jpaquerydsl

Spring JPA deleteInBatch causes StackOverflow


I have a question to deleting Items from db using deleteInBatch. I have an object A having a list of Objects B like:

class A {
private List <B>;
}

The list contains more than 7k elements. So now I have to remove A and all its elements. I tried via deleteInBatch but I get

org.springframework.web.util.NestedServletException: Handler processing failed;
nested exception is java.lang.StackOverflowError

Deleting the items with a sipmle delete method works but it takes more than 5 minutes. My delete code is:

public void delete(Long id) {
A a = repository.findOne(id);
deleteElements(a);
repository.delete(a);
}

private void deleteElements(A a) {
repository.deleteInBatch(a.getListOfB);
}

Is there a good solution to speed up the deleting process or how to change so that deleteinbatch does not take all hibernate stack - without increasing it?

The complete Stacktrace:

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.StackOverflowError
org.springframework.web.servlet.DispatcherServlet.triggerAfterCompletionWithError(DispatcherServlet.java:1259)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:945)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:936)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:827)
javax.servlet.http.HttpServlet.service(HttpServlet.java:620)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:812)
javax.servlet.http.HttpServlet.service(HttpServlet.java:727)
org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:163)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:206)
net.bull.javamelody.MonitoringFilter.doFilter(MonitoringFilter.java:179)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:330)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:118)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:342)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)

And so on...

root cause

java.lang.StackOverflowError
org.hibernate.hql.internal.ast.tree.SqlNode.<init>(SqlNode.java:34)
sun.reflect.GeneratedConstructorAccessor36.newInstance(Unknown Source)
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
java.lang.reflect.Constructor.newInstance(Constructor.java:526)
java.lang.Class.newInstance(Class.java:379)
org.hibernate.hql.internal.ast.SqlASTFactory.create(SqlASTFactory.java:256)
antlr.ASTFactory.create(ASTFactory.java:153)
antlr.ASTFactory.create(ASTFactory.java:186)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2018)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2026)
org.hibernate.hql.internal.antlr.HqlSqlBaseWalker.logicalExpr(HqlSqlBaseWalker.java:2026)

And so on....


Solution

  • in your case, the delete query will be translated by JpaRepository to be looks like this.

    delete from [table_name] where [criteria] = id or [criteria] = id (and so on...)
    

    the jvm throws a stack overflow error because the HqlSqlBaseWalker is trying to search all the or (or basically the where criteria) statement

    I guess, in your case, you could try to generate your own delete query and then execute it or you could try to split the data into few lists.