В вашем случае, похоже, что вы пытаетесь выполнить две транзакции в одном сеансе.Самый простой способ сделать это будет выглядеть следующим образом:
Session session = // you acquire a session from somewhere
try {
// First trx
session.getTransaction().begin();
session.save( c1 );
session.save( c2 );
c3.setCustName( "Robby" );
session.save( c3 );
// at this point nothing has been sent to the database
// if you want to send it to the db and start a new trx
// you don't need to use flush, just commit it.
session.getTransaction().commit();
// Start a new trx
session.getTransaction().begin();
session.save( c4 );
session.save( c5 );
session.getTransaction().commit();
}
catch ( Exception e ) {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
throw e;
}
finally {
if ( session != null && session.isOpen() ) {
session.close();
}
}
Основная проблема заключается в том, что существует вероятность того, что первая транзакция пройдет без проблем, но ваша вторая транзакция завершится неудачно, что зависит от вашего варианта использования.может означать несовместимое состояние базы данных, когда вы хотите, чтобы все было зафиксировано или вообще ничего не было.
Лучшей реализацией было бы следующее:
Session session = // you acquire a session from somewhere
try {
// First trx
session.getTransaction().begin();
session.save( c1 );
session.save( c2 );
c3.setCustName( "Robby" );
session.save( c3 );
session.save( c4 );
session.save( c5 );
session.getTransaction().commit();
}
catch ( Exception e ) {
if ( session.getTransaction().isActive() ) {
session.getTransaction().rollback();
}
throw e;
}
finally {
if ( session != null && session.isOpen() ) {
session.close();
}
}
Сказав это, понимайте, что когда Transaction
был помечен для отката либо тем, что вы вызвали Transaction#rollback()
, либо каким-то внутренним кодом обработки исключений, сделавшим то же самое, который нельзя отменить.
Кроме того, обычно подразумевается, что состояние в кэше сеанса для всех намерений и целей не определено.Если вы посмотрите на большинство примеров обработки отката, вы часто увидите, что единственный вариант - закрыть этот сеанс и попытаться начать с нового сеанса, а не просто транзакции.
Таким образом, вы получаете исключение, чтобы запретить пользователям по существу использовать Session или EntityManager, где состояние контекста постоянства, вероятно, не определено из-за активной транзакции, помеченной для отката.