Issue
I am new in Hibernate. I am trying to write a method that will insert or update 50 records then commit it & then again continue to insert. I am doing this because if something happened while inserting the last record I want to retain all previous records in database.
This is what I am doing:
@Override
public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs){
Session session = this.hibernateSessionFactory.getCurrentSession();
int count = 0;
boolean sessionEnded =false;
for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs){
if(sessionEnded){//At the very beginning, the transaction remains open dont know why. So session.getTransaction().begin() causing exception
session.getTransaction().begin();
sessionEnded = false;
}
session.saveOrUpdate(storeDetailsDTOTmp);
if ( ++count % 10 == 0 ) { //If batch size is 50 clear session-level cache & to avoid OutOfMemoryException
logger.info("Clearing session after 50 batch size. Total rows inserted/updated till now: "+ count);
session.getTransaction().commit();
session.flush();
session.clear();
sessionEnded =true;
} else if(count == storeDetailsDTOs.size()){
session.getTransaction().commit();
session.flush();
session.clear();
}
}
logger.info("Insertion completed. Total rows inserted/updated: "+ count);
return true;
}
This is working fine but after the executuion of this method an exception is happening. The return value of this method never returned to the calling method due to this. Can anyone help me? The stacktrace:
com.follett.fd.exception.UniversityWithSimilarAdoptionException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: Transaction not successfully started
at com.follett.fd.service.impl.FFDServiceImpl.populateLocation(FFDServiceImpl.java:194) ~[classes/:na]
at com.follett.fd.controller.FFDServiceController.populateLocation(FFDServiceController.java:74) ~[classes/:na]
at com.follett.fd.controller.FFDServiceController$$FastClassBySpringCGLIB$$2f892fae.invoke(<generated>) ~[classes/:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[spring-core-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:720) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:173) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:655) ~[spring-aop-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at com.follett.fd.controller.FFDServiceController$$EnhancerBySpringCGLIB$$f350f456.populateLocation(<generated>) ~[classes/:na]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_25]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_25]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_25]
at java.lang.reflect.Method.invoke(Method.java:483) ~[na:1.8.0_25]
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:222) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:110) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:814) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:737) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:959) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:893) ~[spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:969) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:871) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:641) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:845) [spring-webmvc-4.2.4.RELEASE.jar:4.2.4.RELEASE]
at javax.servlet.http.HttpServlet.service(HttpServlet.java:722) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:929) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1002) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:585) [tomcat-embed-core-7.0.30.jar:7.0.30]
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:310) [tomcat-embed-core-7.0.30.jar:7.0.30]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_25]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_25]
at java.lang.Thread.run(Thread.java:745) [na:1.8.0_25]
Solution
I have put @Transactional
at the class level. I believe this was causing the issue though I am not sure. After removing it I was getting some error while executing : this.hibernateSessionFactory.getCurrentSession();
. I think I have to set one property for that.
Anyway to achieve what I wanted I modified the method:
@Override
public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs){
Session session = this.hibernateSessionFactory.getCurrentSession();
int count = 0;
boolean sessionEnded =false;
for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs){
session.saveOrUpdate(storeDetailsDTOTmp);
//session.evict(storeDetailsDTOTmp);
if ( ++count % 50 == 0 ) { //If batch size is 50 clear session-level cache & to avoid OutOfMemoryException
logger.info("Clearing session after 50 batch size.");
session.flush();
session.clear();
}
}
return true;
}
I am calling this method after having 50 records to insert. Please note I have kept the @Transactional
annotation at class level after modifying the method.
Answered By - Sumit
Answer Checked By - Timothy Miller (JavaFixing Admin)