springmvchibernate restful(并发)问题
spring mvc hibernate restful (concurrency) issue
最近我遇到了一个web应用程序问题。我将springmvcrestful应用程序与hibernate一起用作jpa。
客户端可以使用以下格式构建xml文件:
<SCCF>
<registerSCCF>...</registerSCCF>
...
<registerSCCF>...</registerSCCF>
</SCCF>
然后,web应用程序将registerCCF标记中的每个数据映射到一个类,并将其保存在数据库中。
现在我遇到的问题是,当我使用soapui和多线程测试时,我总是得到异常
[ERROR]发生断言失败(这可能表明Hibernate中存在错误,但更可能是由于不安全地使用会话)org.hubinate.AssertionFailure:draft.persistence.entity.dcrm.CustomersNoneSSO条目中的id为null(发生异常后不刷新会话)
或
由:org.hubinate.hibernate引起异常:级联过程中的刷新是危险的
或
org.hibernate.SessionException:会话已关闭!
这是服务层代码:
@Transactional("dcrm")
public boolean postSCCFService(SCCFVO sccf){
CustomersNoneSSO cns = new CustomersNoneSSO();
cns.setAppid(sccf.getAppid());
cns.setCustomer_name(sccf.getCustomer_name());
cns.setCustomer_gender(sccf.getCustomer_gender());
cns.setContact_mobile(sccf.getContact_mobile());
cns.setContact_email(sccf.getContact_email());
cns.setAddress_province(sccf.getAddress_province());
cns.setAddress_city(sccf.getAddress_city());
cns.setCustomer_address(sccf.getCustomer_address());
cns.setCustomer_occupation(sccf.getCustomer_occupation());
cns.setPurchase_brand(sccf.getPurchase_brand());
cns.setPurchase_model(sccf.getPurchase_model());
cns.setPurchase_date(sccf.getPurchase_date());
cns.setPurchase_budget(sccf.getPurchase_budget());
cns.setOwncar_selected(sccf.getOwncar_selected());
cns.setOwncar_model(sccf.getOwncar_model());
cns.setTestdrive_permission(sccf.getTestdrive_permission());
cns.setMarketing_permission(sccf.getMarketing_permission());
Timestamp t = new Timestamp(new Date().getTime());
cns.setInsert_timestamp(t);
cns.setUpdate_timestamp(t);
cnsDao.makePersistent(cns);
}
如果我将所有的setter设置为静态值,如:
cns.setContact_email("test@test.test");
应用程序在多线程测试中运行良好,而不是使用参数中的值。
有控制器调用的服务方法:
@RequestMapping(value = "/test",method=RequestMethod.POST)
public @ResponseBody SCCFResponseList getPostResults(@RequestBody SCCFVOList sccf){
...
for(SCCFVO sccfvo : sccf.getSCCFVOList()){
...
boolean result = sccfservice.postSCCFService(sccfvo);
...
}
...
}
public class SCCFVOList {
这是请求主体类:
@XmlElement(name="registerSCCF")
public class SCCFVOList {
private Vector<SCCFVO> SCCFVOList = null;
public Vector<SCCFVO> getSCCFVOList(){
return SCCFVOList;
}
public void setSCCFVOList(Vector<SCCFVO> SCCFVOList){
this.SCCFVOList = SCCFVOList;
}
}
这里是dao
public class CNSDao extends GenericHibernateDAO<CustomersNoneSSO, Long> {}
public abstract class GenericHibernateDAO<T, ID extends Serializable>
implements GenericDAO<T, ID> {
private Class<T> persistentClass;
private Session session;
SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
public GenericHibernateDAO() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass()
.getGenericSuperclass()).getActualTypeArguments()[0];
}
@SuppressWarnings("unchecked")
public void setSession(Session s) {
this.session = s;
}
protected Session getSession() {
session = sessionFactory.getCurrentSession();
if (session == null)
throw new IllegalStateException(
"Session has not been set on DAO before usage");
return session;
}
public Class<T> getPersistentClass() {
return persistentClass;
}
@SuppressWarnings("unchecked")
public T makePersistent(T entity) {
getSession().saveOrUpdate(entity);
return entity;
}
public void makeTransient(T entity) {
getSession().delete(entity);
}
...
}
控制器方法或服务方法应该有问题。仍然不知道出了什么问题。
您的dao存在缺陷。
你的dao是一个单身汉,只有一个。Hibernate Session
对象不是线程安全的,不应该跨线程使用。
您有1个dao,2个线程,线程1获得会话的实例X1,线程2将其重置为实例X2,现在它们突然共享同一个会话,更不用说线程1甚至可能在2个不同的会话上运行。
正如我在评论中提到的,永远不要将Session
存储在实例变量中。移除它。
public abstract class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {
private Class<T> persistentClass;
private SessionFactory sessionFactory;
public GenericHibernateDAO() {
this.persistentClass = (Class<T>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
public void setSessionFactory(SessionFactory sessionFactory){
this.sessionFactory = sessionFactory;
}
protected Session getSession() {
return sessionFactory.getCurrentSession();
}
此外,我还建议放弃此功能,转而使用SpringDataJPA,这样可以省去创建和维护自己的泛型dao的麻烦。(您提到您使用JPA,如果实体被注释,那么应该很容易做到)。
- 在指令控制器中使用$attrs时出现问题
- 将PHP变量传递给jQuery时遇到问题
- Canvas Html5绘图应用程序,移动画布会导致重大问题
- 参数变量出现ngTable指令问题
- 剑道网格jQuery动画()问题
- 我的jQuery插件参数没有正确启动,遇到了问题
- Phonegap-(安卓/iphone)多个图像的图像库出现问题
- TableExport jquery插件:文件名和扩展名问题
- JavaScript Pub/Sub属性访问问题
- JavaScript异步问题
- 如何解决Yii中的页面刷新问题
- 一个承诺换多个承诺-并发问题
- node.js http服务器并发问题
- JavaScript (缺乏) 并发[线程] (非)问题
- 如何在尝试打印存在警报的URL时解决并发问题
- 从Chrome扩展在页面中注入Javascript:并发问题
- Javascript和并发问题
- springmvchibernate restful(并发)问题
- 如何在不并发问题的情况下替换PHP文件的内容
- Javascript并发问题——我需要一种方法来检查文件加载是否已经完成