最近我遇到了一个web应用程序的问题。我使用spring mvc restful应用程序和hibernate一起使用jpa。spring mvc hibernate restful(concurrency)问题
客户端可以使用这个格式建立一个XML文件:
<SCCF>
<registerSCCF>...</registerSCCF>
...
<registerSCCF>...</registerSCCF>
</SCCF>
网络应用程序将随后registerSCCF标签内的每一个数据映射到一个类,并将其保存在数据库中。
现在我的问题的痛苦,当我使用的soapUI和多线程测试测试它,我总是得到异常
[错误]断言失败发生(这可能表明在Hibernate中的一个bug,但更可能是由于不安全使用会话) org.hibernate.AssertionFailure:在draft.persistence.entity.dcrm.CustomersNoneSSO进入空ID(发生异常后不要冲洗会议)
或
造成的:org.hibernate.HibernateException:层叠期间同花顺是危险
或
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);
}
如果我设置所有的设置器,以静态值,如:
cns.setContact_email("[email protected]");
,而不是使用从该参数的值,则该应用多线程测试运行良好。
有控制器调用服务方法:
@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;
}
}
而且这里的道
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发布代码时有问题。 – 2014-10-07 14:06:37
这是循环应该发生在控制器中的一个好处。但是他们确实全部保存在数据库中,除了少数几个发生错误时。无论如何,我会发布道。 – fe3o4 2014-10-07 14:08:41
还有你的问题......永远不要*从不**(从不提及**)会话存储在一个成员变量中......'Session'不是线程安全的,你有一个实例现在想象一下多线程会发生什么......删除存储(和setter!)并始终使用'sessionFactory.getCurrentSession()'。 – 2014-10-07 14:14:04