问题
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