请注意,当你配置Hibernate事务工厂的时候,在一个BMT session bean中,你应该选择  org.hibernate.transaction.JTATransactionFactory,在一个 CMT session bean中选择 org.hibernate.transaction.CMTTransactionFactory。 记住,同时也要设置 org.hibernate.transaction.manager_lookup_class。
如果你使用CMT环境,并且让容器自动同步和关闭session,你可能也希望在你代码的不同部分使用 同一个session。一般来说,在一个非托管环境中,你可以使用一个 ThreadLocal 变量来持有这个session,但是单个EJB方法调用可能会在不同的线程中执行(举例来说,一个session bean调用另一个session bean)。如果你不想在应用代码中被传递Session对 象实例的问题困扰的话,那么SessionFactory 提供的  getCurrentSession()方法就很适合你,该方法返回一个绑定到JTA事务 上下文环境中的session实例。这也是把 Hibernate集成到一个应用程序中的最简单的方法!这个“当 前的”session总是可以自动同步和自动关闭(不考虑上述的属性设置)。我们的 session/transaction 管理代码减少到如下所示:


 
 
 代码内容
// CMT idiom
Session sess = factory.getCurrentSession();

// do some work
... 

换句话来说,在一个托管环境下,你要做的所有的事情就是调用 SessionFactory.getCurrentSession(),然后进行你的数据访问,把其余的工作 交给容器来做。事务在你的session bean的部署描述符中以可声明的方式来设置。session的生命周期完全 由 Hibernate来管理。
对after_statement连接释放方式有一个警告。因为JTA规范的一个很愚蠢的限制,Hibernate 不可能自动清理任何未关闭的ScrollableResults 或者Iterator,它们是由scroll()或iterate()产生的。你 must通过在finally块中,显式调用ScrollableResults.close()或者Hibernate.close (Iterator)方法来释放底层数据库游标。(当然,大部分程序完全可以很容易的避免在CMT代码中出现scroll()或iterate()。)

12.2.3.异常处理
如果 Session 抛出异常 (包括任何SQLException), 你应该立即回滚数据库事务,调用 Session.close() ,丢弃该  Session实例。Session的某些方法可能会导致session 处于不一致的状态。所有由Hibernate抛出的异常都视为不可以恢复的。确保在 finally 代码块中调用close()方法,以关闭掉 Session。
HibernateException是一个非检查期异常(这不同于Hibernate老的版本), 它封装了Hibernate持久层可能出现的大多数错误。我们的观点是,不应该强迫应用程序开发人员 在底层捕获无法恢复的异常。在大多数软件系统中,非检查期异常和致命异常都是在相应方法调用 的堆栈的顶层被处理的(也就是说,在软件上面的逻辑层),并且提供一个错误信息给应用软件的用户 (或者采取其他某些相应的操作)。请注意,Hibernate也有可能抛出其他并不属于  HibernateException的非检查期异常。这些异常同样也是无法恢复的,应该 采取某些相应的操作去处理。
在和数据库进行交互时,Hibernate把捕获的SQLException封装为Hibernate的 JDBCException。事实上,Hibernate尝试把异常转换为更有实际含义 的JDBCException异常的子类。底层的SQLException可以 通过 JDBCException.getCause()来得到。Hibernate通过使用关联到 SessionFactory上的 SQLExceptionConverter来 把SQLException转换为一个对应的JDBCException 异常的子类。默认情况下, SQLExceptionConverter可以通过配置dialect 选项指定;此外,也可以使用用户自定义的实现类(参考 javadocs SQLExceptionConverterFactory类来了解详情)。标准的 JDBCException子类型是:
JDBCConnectionException - 指明底层的JDBC通讯出现错误
SQLGrammarException - 指明发送的SQL语句的语法或者格式错误
ConstraintViolationException - 指明某种类型的约束违例错误
LockAcquisitionException - 指明了在执行请求操作时,获取 所需的锁级别时出现的错误。
GenericJDBCException - 不属于任何其他种类的原生异常

12.3.乐观并发控制(Optimistic concurrency control)
唯一能够同时保持高并发和高可伸缩性的方法就是使用带版本化的乐观并发控制。版本检查使用版本号、 或者时间戳来检测更新冲突(并且防止更新丢失)。 Hibernate为使用乐观并发控制的代码提供了三种可 能的方法,应用程序在编写这些代码时,可以采用它们。我们已经在前面应用程序长事务那部分展示了 乐观并发控制的应用场景,此外,在单个数据库事务范围内,版本检查也提供了防止更新丢失的好处。
12.3.1.应用程序级别的版本检查(Application version checking)
未能充分利用Hibernate功能的实现代码中,每次和数据库交互都需要一个新的 Session,而且开发人员必须在显示数据之前从数据库中重 新载入所有的持久化对象实例。这种方式迫使应用程序自己实现版本检查来确保 应用程序事务的隔离,从数据访问的角度来说是最低效的。这种使用方式和  entity EJB最相似。