回滚是否会终止会话?

时间:2018-05-26 12:58:54

标签: hibernate session transactions

我在以下情况下遇到以下异常:

java.lang.IllegalStateException: Session/EntityManager is closed

我正在创建一个使用session.save()保存对象的事务; 我还没有提交事务,但我正在使用flush将数据发送到数据库。任何人都可以清除我的回滚概念吗?它是如何工作的?使用flush而不是提交。

任何人都可以在我的代码下面解释我,我刚刚开始学习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 :(得分:2)

在您的用例中,您尝试完成的操作似乎是使用同一会话执行两个事务。最简单的方法就是这样

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,其中由于活动事务已被标记为回滚而导致持久性上下文状态可能未定义。

答案 1 :(得分:-1)

要检查transaction.rollback()对Session和Transaction本身的作用,我编写了以下代码并进行了测试。

       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.Session脱离了交易。
3.会议仍然开放 4.Session仍然保持联系。

因此,您仍然可以使用此会话再次启动新事务,它应该可以正常工作。 希望这能解答你对tr.rollback()的所有疑问。