Я использую класс без сохранения состояния EJB для обновления объекта сохранения, находящегося в базе данных. Метод в EJB вызывает класс реализации, где выполняется работа. Я считаю, что причиной этой проблемы является то, что объект с именем Foo
имеет отношение oneToMany с сущностью Bar
. Делаются, и сеанс обновляется с помощью Foo
, который "каскадирует" до Bar
. Когда происходит событие StaleObjectStateException
, транзакция не полностью откатывается, что вызывает очевидные причины.
EJB
private Session getSession() throws BusinessException {
if( this.sess == null ) {
ServiceLocator locator = new ServiceLocator();
SessionFactory sf = locator.getHibernateSessionFactory();
this.sess = sf.openSession();
}
return this.sess;
}
private ProductionOrderImpl getImpl() throws BusinessException {
if( this.impl == null ) {
this.impl = new ProductionOrderImpl( getSession() );
}
return this.impl;
}
public void cutoffOrders( ) throws Exception {
Transaction tx = null;
try {
tx = getSession().beginTransaction();
getImpl().cutOffFoos(fooTime);
tx.commit();
} catch (StaleObjectStateException e1){
if (tx != null) tx.rollback();
logger.error( "Failed to cutoff order : " + e1 );
throw new Exception( LocaleMgr.getMessage());
}
finally {
// reset implementation object, close session,
// and reset session object
impl = null;
sess.close();
sess = null;
}
}
Реализация
public ProductionOrderImpl(Session sess) {
this.sess = sess;
}
public void cutoffFoos( Timestamp fooTime) throws Exception {
... Code that gets fooList ...
if( fooList != null ) {
for( Foo foo: fooList ) {
for( Bar bar : foo.getBarList() ) {
... Code that does things with existing Barlist ...
if( ... ) {
... Code that makes new Bar object ...
foo.getBarList().add(bar2);
}
}
sess.update( foo );
}
}
}
Релевантный код Foo:
@OneToMany(cascade=CascadeType.ALL, mappedBy="foo")
@OrderBy("startTime DESC")
Set<Bar> barList;
Итак, в основном, когда транзакция пытается откат, части, которые были изменены, возвращаются, но новые записи Bar (bar2 в коде) остаются.
Любое руководство будет оценено по достоинству. Как я уже сказал, я считаю, что ошибка здесь связана с sess.update(foo)
; возможно, что-то делать с autocommit
, но по умолчанию оно должно быть выключено.
Я считаю, что происходит то, что Session.Update(foo) в свою очередь создает две отдельные транзакции. В частности, обновляется Foo
(SQL UPDATE), но сохраняется Bar
(SQL INSERT). Так как контекст транзакции будет реально видеть SQL UPDATE, это все, что он меняет. Вам придется подробнее изучить это.
Я попытался изменить Session.FlushMode
на COMMIT
, но он по-прежнему не исправляет проблему. Однако он частично устраняет проблему. Он будет откатывать записи должным образом, за исключением конкретной записи, которая вызывает исключение StaleObjectStateException. Эта конкретная запись фактически удаляется прямо из базы данных...