简体   繁体   English

无法提交休眠事务

[英]Could not commit Hibernate transaction

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. 我正在尝试编写一种方法,该方法将插入或更新50条记录,然后提交并再次继续插入。 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]

You open session only if sessionEnded is true but you set it to true only after session.getTransaction().commit() . 仅当sessionEndedtrue时才打开会话,但仅在session.getTransaction().commit()之后将其设置为true Better solution would be to start and end session outside the loop. 更好的解决方案是在循环外部开始和结束会话。

I have put @Transactional at the class level. 我把@Transactional放在了班级。 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(); 删除它之后,我在执行时遇到一些错误: 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. 我要插入50条记录后调用此方法。 Please note I have kept the @Transactional annotation at class level after modifying the method. 请注意,修改方法后,我在类级别保留了@Transactional批注。

Thanks for everyone's help!!. 谢谢大家的帮助!

Here is the code where you can flush the records into DB after 50 records but committing/rollback all in case of failure which is normally the scenario but If you want to commit 50 records then execute commit after clear. 这是代码,您可以在50条记录之后将记录刷新到DB中,但是在发生故障的情况下会全部提交/回滚(通常是这种情况),但是如果您要提交50条记录,则在清除后执行commit。

    public void insert(List<T> items) {

    //begin transaction
    for (int i = 0; i < items.size(); i++) {
        T item = items.get(i);
        session.save(item);
        if (i % 50 == 0) {
            session.flush();
            session.clear();
        }           
    }
    session.flush();
    session.clear();

    //commit transaction
}

There is a mistake in the flag check which makes the transaction not to begin. 标志检查中有一个错误,使事务无法开始。 I have made the changes hope this will work. 我已经进行了更改,希望这会起作用。

@Override 
public boolean updateStoreDetails(List<StoreDetailsDTO> storeDetailsDTOs)
{ 
Session session = this.hibernateSessionFactory.getCurrentSession(); 
int count = 0; 
boolean sessionEnded =true; for(StoreDetailsDTO storeDetailsDTOTmp : storeDetailsDTOs)
{ 
if(sessionEnded)
{
 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;
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM