oracle 会话/实体管理器已关闭
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/46754143/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
session/entitymanager is closed
提问by sagar limbu
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).
我有这个 hibernate dao,在我的本地机器上测试时它工作正常。但是对于某些事务,它会抛出 IllegalStateException。我相信这是因为多个用户同时点击。(我可能错了)。
UpdatePaymentDao
更新PaymentDao
@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
<?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
.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
回答by Baptiste Beauvais
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.
你不能像那样使用Session
andTransaction
作为你的 dao 的类成员。Session/EntityManager
假设受工作单元的限制,它们不是线程安全的。
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.
在您当前的状态下,由于 Spring DI 将 bean 创建为单例,如果两个线程同时使用 dao,第二个线程将覆盖两者Session
和Transaction
成员,这就是为什么我想您会得到 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.
您必须通过将它们用作方法中的变量来使它们成为线程作用域,或者,如果您不需要 hibernate 的特定方法,则可以在 Spring 中进行完整的 JPA 配置,并使用它@PersistenceContext/@PersistenceUnit
来让框架处理该问题。
回答by RaM PrabU
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 closeit. So make sure declaring these variable inside your local variable. The Scope of declaration of variable matters here.
Spring 将创建 DA 类的单例副本。在多线程场景中,当线程 t1 正在处理会话/事务,而共享相同会话/事务的线程 t2 可能会 关闭它。因此,请确保在本地变量中声明这些变量。变量声明的范围在这里很重要。