Comparing Container-managed and Locally Defined Resources
你可以在容器管理的 JNDI SessionFactory 和本地定义的 JNDI SessionFactory 之间进行切换,而不需要改变一行应用程序代码。将资源定义保留在容器中还是在应用程序中保留在本地,主要是你使用的事务策略的问题。与 Spring 定义的本地 SessionFactory 相比,手动注册的 JNDI SessionFactory 并没有提供任何好处。通过 Hibernate 的 JCA 连接器部署 SessionFactory 可以提供参与 Java EE 服务器管理基础架构的附加价值,但除此之外并没有增加实际价值。
Spring 的事务支持并不与容器绑定。当配置了 JTA 以外的任何策略时,事务支持也可以在独立或测试环境中工作。特别是在单数据库事务的典型情况下,Spring 的单资源本地事务支持是 JTA 的轻量级和强大的替代品。当你使用本地 EJB 无状态会话 Bean 来驱动事务时,你同时依赖于 EJB 容器和 JTA,即使你只访问一个数据库并且只使用无状态会话 Bean 来通过容器管理的事务提供声明性事务。以编程方式直接使用 JTA 也需要一个 Java EE 环境。JTA 并不只涉及 JTA 本身和 JNDI DataSource 实例方面的容器依赖性。对于非 Spring、JTA 驱动的 Hibernate 事务,你必须使用 Hibernate JCA 连接器或额外的 Hibernate 事务代码,并配置 TransactionManagerLookup 以进行适当的 JVM 级缓存。
Spring 驱动的事务可以与本地定义的 Hibernate SessionFactory 一起工作,就像它们与本地 JDBC DataSource 一起工作一样,只要它们访问单一数据库。因此,只有当你有分布式事务需求时,你才需要使用 Spring 的 JTA 事务策略。JCA 连接器需要特定于容器的部署步骤,而且(显然)首先要支持 JCA。这种配置比部署一个具有本地资源定义和 Spring 驱动的事务的简单 Web 应用需要更多的工作。另外,如果你使用 WebLogic Express 等不提供 JCA 的容器,你通常需要企业版的容器。一个具有本地资源和跨越单个数据库的事务的 Spring 应用可以在任何 Java EE Web 容器(没有 JTA、JCA 或 EJB)中使用,比如 Tomcat、Resin,甚至是普通的 Jetty。此外,你可以很容易地在桌面应用程序或测试套件中重用这样一个中间层。
综合考虑,如果你不使用 EJB,坚持使用本地 SessionFactory 设置和 Spring 的 HibernateTransactionManager 或 JtaTransactionManager。你可以得到所有的好处,包括适当的事务性 JVM 级缓存和分布式事务,而没有容器部署的不便。通过 JCA 连接器对 Hibernate SessionFactory 进行 JNDI 注册,只有在与 EJB 一起使用时才能增加价值。