我有这个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
答案 0 :(得分:6)
你不能像这样使用Session
和Transaction
作为你的dao的类成员。假设Session/EntityManager
是按工作单元划分的,它们不是线程安全的。
在你当前的状态下,当Spring DI将bean创建为单例时,如果两个线程同时使用dao,则第二个将覆盖Session
和Transaction
成员,这就是为什么我认为你得到的IllegalStateExcepion。
你必须通过在方法中使用它们作为变量来使它们成为线程范围,或者,如果你不需要hibernate的特定方法,你可以在Spring中进行完整的JPA配置并使用@PersistenceContext/@PersistenceUnit
让它们框架处理该问题。
答案 1 :(得分:1)
Spring将创建DA类的单例副本。 在多线程 g场景中,当线程t1正在处理会话/事务时,并且共享相同sesion / transacrtion的线程t2可以关闭它。因此,请确保在局部变量中声明这些变量。变量的声明范围在这里。