0

I have a Spring Boot application that uses Hibernate. Below is the way I get the Hibernate session:

@Transactional
public class ParentDAO {


        @PersistenceContext
        private EntityManager entityManager;

        protected Session getSession() {

            if(entityManager!=null)
                System.out.println("entity manager instantiated...");

            return entityManager.unwrap(Session.class);
        }



}

Then, I have the class which does the database access as the following,

@Repository
@Transactional
@SuppressWarnings("unchecked")
public class GmCircularsDaoImpl extends ParentDAO implements IGmCircularsDAO {


    @Override
    public GmCirculars saveOrUpdate(GmCirculars obj) {

        Session session = null;

        try {


            session= this.getSession(); //Added by Zaid

            session.beginTransaction();
            session.saveOrUpdate(obj);
            session.flush();
            session.getTransaction().commit();

        }
        catch (Exception ex) {
            ex.printStackTrace();
        }
        finally {
            session.close();
            System.out.println("Session closed.");
        }
        return obj;
    }


    @Override
    public List<GmCirculars> find(GmCirculars obj, boolean activeOnly, int startOffset, int maxRows) {
        Session session = null;
        List<GmCirculars> discounts = null;

        try {
            if (null != obj) {

                session= this.getSession(); //Added by Zaid

                Criteria criteria = session.createCriteria(GmCirculars.class);

                if (null != obj.getId() && !BigDecimal.ZERO.equals(obj.getId())) {
                    criteria.add(Restrictions.eq("id", obj.getId()));
                }

                if (StringUtil.isNotNullOrEmpty(obj.getTitle())) {
                    criteria.add(Restrictions.ilike("title", obj.getTitle(), MatchMode.ANYWHERE));
                }

                if(null != obj.getOrganizationId()) {
                    criteria.add(Restrictions.eq("organizationId", obj.getOrganizationId()));
                }


                /*if (null != obj.getTypeId() && !BigDecimal.ZERO.equals(obj.getTypeId())) {
                    criteria.add(Restrictions.eq("typeId", obj.getTypeId()));
                }*/


                if (null != obj.getSerialNo() && !BigDecimal.ZERO.equals(obj.getSerialNo())) {
                    criteria.add(Restrictions.eq("serialNo", obj.getSerialNo()));
                }

                if (null != obj.getYear() && !BigDecimal.ZERO.equals(obj.getYear())) {
                    criteria.add(Restrictions.eq("year", obj.getYear()));
                }


                if (activeOnly) {
                    criteria.add(Restrictions.eq("active", BigDecimal.ONE));
                }
                else {
                    criteria.add(Restrictions.or(Restrictions.ne("active", CommonConstants.DELETED_STATUS), Restrictions.isNull("active"))); //Except for deleted ones -> NVL(active,2)
                }


                //LIMIT startOffset, maxRows;
                criteria.setFirstResult(startOffset);
                criteria.setMaxResults(maxRows);

                criteria.addOrder(Order.desc("id"));
                criteria.setResultTransformer(Criteria.DISTINCT_ROOT_ENTITY);

                System.out.println("criteria: "+ criteria.toString());
                discounts = criteria.list();
                System.out.println("returned list from db:"+discounts);

                //session.getTransaction().commit();

            }

        }
        catch (Exception e) {
            e.printStackTrace();
        }
        finally {
            session.close();
        }
        return discounts;
    }

}

The method find(GmCirculars obj, boolean activeOnly, int startOffset, int maxRows) was first called for some query and it works just fine. However, after that I called saveOrUpdate(GmCirculars obj) , but I got the following errors on the line:

session.beginTransaction();

The error:

java.lang.IllegalStateException: Transaction already active
    at org.hibernate.engine.transaction.internal.TransactionImpl.begin(TransactionImpl.java:74)
    at org.hibernate.internal.AbstractSharedSessionContract.beginTransaction(AbstractSharedSessionContract.java:467)
    at ae.gov.adm.saeed.dao.impl.circulars.GmCircularsDaoImpl.saveOrUpdate(GmCircularsDaoImpl.java:49)
    at ae.gov.adm.saeed.dao.impl.circulars.GmCircularsDaoImpl$$FastClassBySpringCGLIB$$babc932a.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:769)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:139)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:99)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:747)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:689)
    at ae.gov.adm.saeed.dao.impl.circulars.GmCircularsDaoImpl$$EnhancerBySpringCGLIB$$718dc221.saveOrUpdate(<generated>)
    at ae.gov.adm.saeed.service.circulars.CircularsService.saveOrUpdate(CircularsService.java:37)
    at ae.gov.adm.CircularsMicroservice.saveCircularView(CircularsMicroservice.java:109)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:190)
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:138)
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:888)
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:793)
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:87)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1040)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:943)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006)
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:898)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:503)
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:590)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:100)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.FormContentFilter.doFilterInternal(FormContentFilter.java:93)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.boot.actuate.metrics.web.servlet.WebMvcMetricsFilter.doFilterInternal(WebMvcMetricsFilter.java:108)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:201)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:119)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:541)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
    at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:367)
    at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:65)
    at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:860)
    at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1598)
    at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:748)

I tried to close the session before reusing it like

    if(session.isOpen())
        session.close();

I also tried to remove this line whenever I access the database again,

    session.beginTransaction();

I checked the answer here but doesn't seem to work for my particular case.

All these attempts fail and I keep getting errors. How to solve the problem? Thanks.

Traveling Salesman
  • 2,209
  • 11
  • 46
  • 83
  • Either use @Transactional or create new transaction using SessionFactory sessionFactory = entityManager.getEntityManagerFactory().unwrap(SessionFactory.class); Session session = sessionFactory.openSession(); – Miller Cy Chan Mar 03 '20 at 07:23
  • 1
    Why are you using the session? Just use the `EntitiyManager` and `persist` to achieve the same. With the current release/state of JPA you generally don't want/need to use the underlying Hibernate Session. This will only complicate your code. That being said, don't start a transaction nor commit it (spring already does that) and definitly don't close the session! which will mess-up proper handling in Spring. – M. Deinum Mar 03 '20 at 07:25

1 Answers1

2

Your classes are annotated with @Transactional which means Spring has already wrapped all methods with transaction handling. If you look at the stack trace you can see a line

at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:366)

which reveals that the annotation is working. Hibernate will flush and commit automatically before leaving the transaction. Just remove the manual handling of transactions from you code, as well as the Session.close() calls and it should work...

Per Huss
  • 4,755
  • 12
  • 29