Завершает ли откат сеанс? - PullRequest
0 голосов
/ 26 мая 2018

Я получаю следующее исключение для сценария ниже:

java.lang.IllegalStateException: Session/EntityManager is closed

Я создаю транзакцию, в которой я сохраняю объекты с помощью session.save ();Я не совершил транзакцию, но я использую flush для отправки данных в базу данных.Кто-нибудь может очистить мою концепцию отката?как это работает?используя flush, а не commit.

Может кто-нибудь объяснить мне мой код ниже, я только начал изучать hibernate.

Transaction tr1 = session.beginTransaction();
     session.save(c1);
     session.save(c2);
     c3.setCustName("Robby");
     session.save(c3);
     session.flush();
     tr1.rollback();

     session.save(c4);//Here its throwing above mentioned exception.
     session.save(c5);
     tr1.commit();  

Заранее спасибо ..!

Ответы [ 2 ]

0 голосов
/ 26 мая 2018

Чтобы проверить, что транзакция.rollback () делает с вашим сеансом и самой транзакцией, я написал следующий код и протестировал.

       SessionFactory sf = cf.configure().buildSessionFactory();
       Session session = sf.openSession();

       Transaction tr = ss.beginTransaction();

        System.out.println( "******** before rollback ************");
        System.out.println("is TR active "+tr.isActive());      
        System.out.println("joind with TR "+session.isJoinedToTransaction());
        System.out.println("is open "+session.isOpen());
        System.out.println("is connected "+session.isConnected());

        tr.rollback();

        System.out.println( "******** After rollback ************");
        System.out.println(" is TR active "+tr.isActive());
        System.out.println("joind with TR "+session.isJoinedToTransaction());
        System.out.println("is open "+session.isOpen());
        System.out.println("is connected "+session.isConnected());

В выводе я получил это,

******** до отката ************
активен TR true
соединен с TR true
открыт true
подключенtrue

******** После отката ************

активен TR false
соединиться с TR false
открыто true
подключено true

Как видно из этого вывода, после вызова tr.rollback (),

1.Транзакция, котораяВы начали ранее, больше не активны.
2.Сессия отсоединяется от транзакции.
3.Сессия все еще остается открытой.
4.Сессия все еще остается подключенной.

Таким образом, вы можете снова начать новую транзакцию с этим сеансом, и она должна работать нормально.надеюсь, что это ответит на все ваши вопросы о tr.rollback ().

0 голосов
/ 26 мая 2018

В вашем случае, похоже, что вы пытаетесь выполнить две транзакции в одном сеансе.Самый простой способ сделать это будет выглядеть следующим образом:

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, где состояние контекста постоянства, вероятно, не определено из-за активной транзакции, помеченной для отката.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...