Недавно у меня возникла проблема с веб-приложением. Я использую Spring mvc restful application вместе с hibernate как jpa.spring mvc hibernate restful (concurrency) issue
Клиент может создать файл XML, используя этот формат:
<SCCF>
<registerSCCF>...</registerSCCF>
...
<registerSCCF>...</registerSCCF>
</SCCF>
Веб-приложение будет отображение каждые данные внутри registerSCCF тега класса и сохранить его в базе данных.
Теперь мучаюсь с проблемой, что когда я проверить его с помощью SoapUI и тест многопоточность, я всегда получаю исключение
[ERROR] сбой утверждение произошло (это может указывать на ошибку в Hibernate, но более вероятно, из-за небезопасное использование сессии) org.hibernate.AssertionFailure: нулевой идентификатор в записи draft.persistence.entity.dcrm.CustomersNoneSSO (не сбрасывают сессии после того, как происходит исключение)
или
Вызванный: 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);
}
...
}
Там должно быть что-то неправильный метод контроллера или метод обслуживания. По-прежнему не знаю, что было не так.
Сначала я ожидал бы, что служба сохранит все или нет, я бы не зациклился на контроллере, но это я. Похоже, у вас есть проблема в вашем сообщении о дао. –
Это хороший момент, когда цикл должен проходить в контроллере. Но они действительно сохранены в базе данных, за исключением нескольких случаев, когда исполнилось. Я все равно отправлю дао. – fe3o4
И есть ваша проблема ... НИКОГДА * НИКОГДА * ** НИКОГДА ** (я не упоминал НИКОГДА) хранят сеанс в переменной-члене ... «Сессия» не является потокобезопасной, у вас есть один экземпляр дао, теперь представьте, что происходит с несколькими потоками .... Удалите хранилище (и setter!) и всегда используйте 'sessionFactory.getCurrentSession()'. –