session/entitymanager is closed

蹲街弑〆低调 提交于 2021-02-18 12:17:01

问题


i have this hibernate dao and it works fine while testing in my local machine. but for some transaction it throws IllegalStateException. i believe it is because multiple users hitting at same time.(i may be wrong).

UpdatePaymentDao

@Repository
public class UpdatePaymentImpl implements UpdatePayment {


    @Autowired
    SessionFactory sessionFactory;
    Session session;
    Transaction trans;

    private static final long LIMIT = 100000000000L;
    private static final long LIMIT2 = 10000000000L;
    private static long last = 0;


    public static long getUniqueID() {
        // 10 digits.
        long id = (System.currentTimeMillis() % LIMIT) + LIMIT2;
        System.out.println("id"+id);
        System.out.println("system time"+System.currentTimeMillis());
        System.out.println("milssiiiiii=============="
                + System.currentTimeMillis());
        if (id <= last) {
            id = (last + 1) % LIMIT;
        }
        return last = id;
    }

    public PaymentResponse updatePayment(@RequestBody FcgoUpdateParam updateParam) {
        FcgoUpdateParam fcgoUpdateParam= new FcgoUpdateParam();
        Double amountPaid=Double.parseDouble(updateParam.getAmountPaid());
        String depositSlioNo=updateParam.getVoucherno();
        String masterId= updateParam.getMasterId();
        String advCode=updateParam.getAdvCode();

        PaymentResponse paymentResponse = new PaymentResponse();

        long uuid = getUniqueID();

        try{

            System.out.println("generated uuid "+uuid);


            DateFormat dateFormat =new SimpleDateFormat("dd-MMM-yy h.mm.ss.000000000 a");
            SimpleDateFormat dms = new SimpleDateFormat("dd-MM-yyyy");
            String cdate = updateParam.getChallanDate();
            Date ddate= dms.parse(cdate);
            String challandate = dateFormat.format(ddate);

            String office = updateParam.getOffice();
            String username = updateParam.getUsername();
            Long id = getIdOnChallanTable()+1L;

            String challanid = String.valueOf(uuid);
            ChallanEntity challanEntity = new ChallanEntity();
            challanEntity.setAdvtcode(updateParam.getAdvCode());
            challanEntity.setAmount(amountPaid);
            challanEntity.setName(updateParam.getName());
            challanEntity.setOffice(office);
            challanEntity.setUsername(username);
            challanEntity.setStatus(updateParam.getStatus());
            challanEntity.setChallandate(challandate);
            challanEntity.setChallanid(uuid);
            challanEntity.setChallantime("null");
            challanEntity.setVoucherno(updateParam.getVoucherno());

            System.out.println(challanEntity.getId());

            System.out.println("challan saved");

            session=sessionFactory.openSession();
            trans=session.beginTransaction();

            Query query= session.createQuery("update CandidateappearagainstadvtcodeEntity cd set 

            cd.paymentstatus='Completed',cd.amountpaid=:depoFee,cd.challanid=:challanid where
             cd.studentmasterid=:masterid and cd.advertisementcode=:advCode");
            System.out.println(updateParam.getAdvCode());
            query.setParameter("depoFee",updateParam.getAmountPaid());
            query.setParameter("challanid",challanid);
            query.setParameter("masterid",masterId);
            query.setParameter("advCode",advCode);
            Query query1 =session.createQuery(" update CandidateappeartoadvtnumberEntity cnd

            set cnd.paymentstatus='Completed', cnd.depositedfee=:depofee where
             cnd.studentmasterid=:masterid
            and cnd.advertisementcode=:advcode");
            String masterId1= updateParam.getMasterId();
            String advCode1=updateParam.getAdvCode();
            System.out.println("updateCandidateappearagainstadvtcodeEntity ");

            query1.setParameter("depofee",amountPaid);
            query1.setParameter("masterid",masterId1);
            query1.setParameter("advcode",advCode1);


            //added code
            final long start = System.nanoTime();
            System.out.println("before executing excute update queries");
            System.out.println("checking update query timings");


            query.executeUpdate();
            query1.executeUpdate();
            //added code
            final long end = System.nanoTime();
            System.out.println("after executing two update queries, it took: " +
            ((end - start) / 1000000) + "ms");

            //printing all values for test
            //printing for candidateappearagainstcode table
            System.out.println("printing candidate appear against code table");
            System.out.println("the received challan id is: " +challanid);
            System.out.println("the received deposited fee is :"+amountPaid);
            System.out.println("the received advt code is : "+advCode);
            System.out.println("the received master id is : "+masterId);


            System.out.println("values committed on psc database");
            try {
                final String uri = "http://xx.x.x.xx:xxxx/FcgoApi/api/savePayment";
                RestTemplate restTemplate = new RestTemplate();
                paymentResponse = restTemplate.postForObject(uri, updateParam,
                PaymentResponse.class);
                if (paymentResponse.getVoucherNo() != null) {
                    challanEntity.setVoucherno(paymentResponse.getVoucherNo());
                    session.save(challanEntity);
                    session.update(challanEntity);
                    trans.commit();
                    return paymentResponse;
                }else {
                    trans.rollback();
                }
            }catch (Exception ex){
                ex.printStackTrace();
                trans.rollback();
            }
        }catch (Exception e){
            System.out.println("update error " +e);
            trans.rollback();

        }finally {
            session.close();
        }
        return paymentResponse;
    }

    // [...]
}

applicationContext.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd">

    <bean class="org.springframework.beans.factory.config.
        PropertyPlaceholderConfigurer">
        <property name="location">
            <value>/WEB-INF/db.properties</value>
        </property>
    </bean>
    <bean id="sessionFactory" 
        class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource"></property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">
                    org.hibernate.dialect.Oracle10gDialect</prop>
                <prop key="hibernate.hbm2ddl.auto">update</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <prop key="hibernate.connection.url">
                    jdbc:oracle:thin:@x.x.x.x:1521:xxx</prop>
                <prop key="hibernate.connection.driver_class">
                    oracle.jdbc.driver.OracleDriver</prop>
                <prop key="hibernate.c3p0.timeout">18000</prop>
            </props>
        </property>
        <property name="packagesToScan">
            <list>
                <value>com.psc</value>
            </list>
        </property>
    </bean>


    <bean id="transactionManager" class="org.springframework.
        orm.hibernate5.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory"/>
    </bean>
    <bean id="dataSource" class="org.springframework.jdbc.
        datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${jdbc.driver}"></property>
        <property name="url" value="${jdbc.url}"></property>
        <property name="username" value="${jdbc.username}"/>
        <property name="password" value="${jdbc.password}"/>
    </bean>

</beans>

error log:

java.lang.IllegalStateException: Session/EntityManager is closed
        at org.hibernate.internal.AbstractSharedSessionContract.
        checkOpen(AbstractSharedSessionContract.java:328)
        at org.hibernate.engine.spi.SharedSessionContractImplementor
        checkOpen(SharedSessionContractImplementor.java:126)
        at org.hibernate.internal.SessionImpl.fireSave(SessionImpl.java:669)
        at org.hibernate.internal.SessionImpl.save(SessionImpl.java:665)
        at org.hibernate.internal.SessionImpl.save(SessionImpl.java:660)
        at com.psc.dao.UpdatePaymentImpl.updatePayment(UpdatePaymentImpl.java:127)
        at com.psc.services.UpdatePaymentServiceImpl.updatePayment
        (UpdatePaymentServiceImpl.java:26)
        at sun.reflect.GeneratedMethodAccessor92.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
        at java.lang.reflect.Method.invoke(Method.java:508)
        at org.springframework.aop.support.AopUtils
        .invokeJoinpointUsingReflection(AopUtils.java:333)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.
        invokeJoinpoint(ReflectiveMethodInvocation.java:190)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.
        proceed(ReflectiveMethodInvocation.java:157)
        at org.springframework.transaction.interceptor.TransactionInterceptor$1
        .proceedWithInvocation(TransactionInterceptor.java:99)
        at org.springframework.transaction.interceptor.TransactionAspectSupport.
        invokeWithinTransaction(TransactionAspectSupport.java:282)
        at org.springframework.transaction.interceptor.TransactionInterceptor.
        invoke(TransactionInterceptor.java:96)
        at org.springframework.aop.framework.
        ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
        at com.sun.proxy.$Proxy32.updatePayment(Unknown Source)
        at com.psc.controls.UpdatePayment.updatePayment(UpdatePayment.java:26)
        at sun.reflect.GeneratedMethodAccessor91.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:55)
        at java.lang.reflect.Method.invoke(Method.java:508)
        at org.springframework.web.method.support.
        InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
        at org.springframework.web.method.support.
        InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
        at org.springframework.web.servlet.mvc.method.annotation.
        ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:97)
        at org.springframework.web.servlet.mvc.method.annotation.
        RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
        at org.springframework.web.servlet.mvc.method.annotation.
        RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
        at org.springframework.web.servlet.mvc.method.
        AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
        at org.springframework.web.servlet.DispatcherServlet.
        doDispatch(DispatcherServlet.java:963)
        at org.springframework.web.servlet.DispatcherServlet
        .doService(DispatcherServlet.java:897)
        at org.springframework.web.servlet.FrameworkServlet
        .processRequest(FrameworkServlet.java:970)
        at org.springframework.web.servlet.FrameworkServlet
        .doPost(FrameworkServlet.java:872)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:661)
        at org.springframework.web.servlet.FrameworkServlet
        .service(FrameworkServlet.java:846)
        at javax.servlet.http.HttpServlet.service(HttpServlet.java:742)
        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:52)
        at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter
        (ApplicationFilterChain.java:193)
update error java.lang.IllegalStateException: org.hibernate.resource.jdbc.internal.LogicalConnectionManagedImpl@4bbb6b39 is closed

回答1:


You mustn't use the Session and Transaction as a class member of your dao like that. Session/EntityManager are suppose to be scoped by unit of work, they are not thread safe.

In your current state, as Spring DI create beans as singleton, if two threads use the dao at the same time the second will overwrite both Session and Transaction members which is why i suppose you get the IllegalStateExcepion.

You have to make them thread scoped by either using them as variables in methods or, if you don't need hibernate's specific method, you could go for a full JPA configuration in Spring and use @PersistenceContext/@PersistenceUnit to let the framework deal with that issue.




回答2:


The Spring will create a singleton copy of the DA class. In a multi threading scenario when a thread t1 is working on a session/transaction and thread t2 which share same sesion/transacrtion may close it. So make sure declaring these variable inside your local variable. The Scope of declaration of variable matters here.



来源:https://stackoverflow.com/questions/46754143/session-entitymanager-is-closed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!