session / entitymanager已关闭

时间:2017-10-15 10:41:17

标签: spring oracle hibernate

我有这个hibernate dao,它在我的本地机器上测试时工作正常。但对于某些事务,它会抛出IllegalStateException。我相信这是因为多个用户同时打。(我可能错了)。

UpdatePaymentDao

@Repository 公共类UpdatePaymentImpl实现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>

错误日志:

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

2 个答案:

答案 0 :(得分:6)

你不能像这样使用SessionTransaction作为你的dao的类成员。假设Session/EntityManager是按工作单元划分的,它们不是线程安全的。

在你当前的状态下,当Spring DI将bean创建为单例时,如果两个线程同时使用dao,则第二个将覆盖SessionTransaction成员,这就是为什么我认为你得到的IllegalStateExcepion。

你必须通过在方法中使用它们作为变量来使它们成为线程范围,或者,如果你不需要hibernate的特定方法,你可以在Spring中进行完整的JPA配置并使用@PersistenceContext/@PersistenceUnit让它们框架处理该问题。

答案 1 :(得分:1)

Spring将创建DA类的单例副本。 在多线程 g场景中,当线程t1正在处理会话/事务时,并且共享相同sesion / transacrtion的线程t2可以关闭它。因此,请确保在局部变量中声明这些变量。变量的声明范围在这里。