Hibernate.orgCommunity Documentation
下面的图表提供了 Hibernate 体系结构的高层视图:
提供 Hibernate 所有运行时体系结构的更多细节不是本文档的范畴。由于 Hibernate 非常灵活,且支持多种应用方案, 所以我们这只描述一下两种极端的情况:“最小”和“全面解决”的体系结构方案。
下图演示了 Hibernate 如何使用数据库和配置信息来为应用程序提供持久化服务(以及持久的对象)。
“最小”的体系结构方案,要求应用程序提供自己的 JDBC 连接并管理自己的事务。这种方案使用了Hibernate API 的最小子集:
“全面解决”的体系结构方案,将应用层从底层的 JDBC/JTA API 中抽象出来,而让 Hibernate 来处理这些细节。
图中各个对象的定义如下:
org.hibernate.SessionFactory
)针对单个数据库映射关系经过编译后的内存镜像,是线程安全的(不可变)。 作为 Session
的工厂和 ConnectionProvider
的客户。SessionFactory
可以在进程或集群的级别上,为那些事务之间可以重用的数据提供可选的二级缓存。
org.hibernate.Session
)表示应用程序与持久储存层之间交互操作的一个单线程对象,此对象生存期很短。其隐藏了 JDBC 连接,也是 Transaction
的工厂。它会持有一个针对持久化对象的必选(第一级)缓存,在遍历对象图或者根据持久化标识查找对象时会用到。
带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。这些对象可能是普通的JavaBeans/POJO,唯一特殊的是他们正与(仅仅一个)Session
相关联。一旦这个 Session
被关闭,这些对象就会脱离持久化状态,这样就可被应用程序的任何层自由使用(例如,用作跟表示层打交道的数据传输对象)。
那些目前没有与 Session
关联的持久化类实例。他们可能是在被应用程序实例化后,尚未进行持久化的对象。也可能是因为实例化他们的 Session
已经被关闭而脱离持久化的对象。
org.hibernate.Transaction
)(可选的)应用程序用来指定原子操作单元范围的对象,它是单线程的,生命周期很短。它通过抽象将应用从底层具体的 JDBC、JTA 以及 CORBA 事务隔离开。某些情况下,一个 Session
之内可能包含多个 Transaction
对象。尽管是否使用该对象是可选的,但无论是使用底层的 API 还是使用 Transaction
对象,事务边界的开启与关闭是必需的。
org.hibernate.connection.ConnectionProvider
)(可选的)生成 JDBC 连接的工厂(同时也起到连接池的作用)。它通过抽象将应用从底层的 Datasource
或 DriverManager
隔离开。仅供开发者扩展/实现用,并不开放给应用程序使用。
org.hibernate.TransactionFactory
)(可选的)生成 Transaction
对象实例的工厂。仅供开发者扩展/实现用,并不开发能够给应用程序使用。
Hibernate 提供了很多可选的扩展接口,你可以通过实现它们来定制你的持久层的行为。具体请参考 API 文档。
在特定“最小”的体系结构中,应用程序可能绕过 Transaction
/TransactionFactory
以及 ConnectionProvider
等 API 直接跟 JTA 或 JDBC 打交道。
一个持久化类的实例可能处于三种不同状态中的某一种。这三种状态的定义则与所谓的持久化上下文(persistence context)有关。Hibernate 的 Session
对象就是这个所谓的持久化上下文。这三种不同的状态如下:
该实例从未与任何持久化上下文关联过。它没有持久化标识(相当于主键值)。
实例目前与某个持久化上下文有关联。它拥有持久化标识(相当于主键值),并且可能在数据库中有一个对应的行。对于某一个特定的持久化上下文,Hibernate 保证 持久化标识与 Java 标识(其值代表对象在内存中的位置)等价。
实例曾经与某个持久化上下文发生过关联,不过那个上下文被关闭了,或者这个实例是被序列化(serialize)到另外的进程。它拥有持久化标识,并且在数据库中可能存在一个对应的行。对于脱管状态的实例,Hibernate 不保证任何持久化标识和 Java 标识的关系。
JMX 是管理 Java 组件的 J2EE 标准。Hibernate 可以通过一个 JMX 标准服务来管理。在这个发行版本中,我们提供了一个 MBean 接口的实现,即 org.hibernate.jmx.HibernateService
。
想要看如何在 JBoss 应用服务器上将 Hibernate 部署为一个 JMX 服务的例子,您可以参考《JBoss 用户指南》。如果你使用 JMX 来部署 Hibernate,JBoss AS 也提供如下好处:
会话管理: Hibernate 的 Session
对象的生命周期可以 自动跟一个 JTA 事务边界绑定。这意味着你无需手工开关 Session
了, 这项工作会由 JBoss EJB 拦截器来完成。你再也不用担心你的代码中的事务边界了(除非你想利用 Hibernate 提供可选的 Transaction
API 来自己写一个便于移植的的持久层)。你通过调用 HibernateContext
来访问 Session
。
HAR 部署: 通常情况下,你会使用 JBoss 的服务部署描述符(在 EAR 或/和 SAR 文件中)来部署 Hibernate JMX 服务。这种部署方式支持所有常见的 Hibernate SessionFactory
的配置选项。不过,你仍需在部署描述符中,列出你所有的映射文的名字。如果你使用 HAR 部署方式, JBoss 会自动探测出你的 HAR 文件中所有的映射文件。
这些选项更多的描述,请参考 JBoss 应用程序用户指南。
Another feature available as a JMX service is runtime Hibernate statistics. See 第 3.4.6 节 “Hibernate 的统计(statistics)机制” for more information.
Hibernate 也可以被配置为一个 JCA 连接器(JCA connector)。更多信息请参看网站。请注意,Hibernate 对 JCA 的支持,仍处于实验性阶段。
使用 Hibernate 的大多数应用程序需要某种形式的“上下文相关的”会话,特定的会话在整个特定的上下文范围内始终有效。然而,对不同类型的应用程序而言,要为什么是组成这种“上下文”下一个定义通常是困难的;不同的上下文对“当前”这个概念定义了不同的范围。在 3.0 版本之前,使用 Hibernate 的程序要么采用自行编写的基于 ThreadLocal
的上下文会话,要么采用 HibernateUtil
这样的辅助类,要么采用第三方框架(比如 Spring 或 Pico),它们提供了基于代理(proxy)或者基于拦截器(interception)的上下文相关的会话。
从 3.0.1 版本开始,Hibernate 增加了 SessionFactory.getCurrentSession()
方法。一开始,它假定了采用 JTA
事务,JTA
事务定义了当前 session 的范围和上下文(scope 和 context)。因为有好几个独立的 JTA TransactionManager
实现稳定可用,不论是否被部署到一个 J2EE
容器中,大多数(假若不是所有的)应用程序都应该采用 JTA
事务管理。基于这一点,采用 JTA
的上下文相关的会话可以满足你一切需要。
更好的是,从 3.1 开始,SessionFactory.getCurrentSession()
的后台实现是可拔插的。因此,我们引入了新的扩展接口(org.hibernate.context.CurrentSessionContext
)和新的配置参数(hibernate.current_session_context_class
),以便对什么是当前会话的范围(scope)和上下文(context)的定义进行拔插。
请参阅 org.hibernate.context.CurrentSessionContext
接口的 Javadoc,那里有关于它的契约的详细讨论。它定义了单一的方法,currentSession()
,特定的实现用它来负责跟踪当前的上下文相关的会话。Hibernate 内置了此接口的三种实现:
org.hibernate.context.JTASessionContext
:当前会话根据 JTA
来跟踪和界定。这和以前的仅支持 JTA 的方法是完全一样的。详情请参阅 Javadoc。
org.hibernate.context.ThreadLocalSessionContext
:当前会话通过当前执行的线程来跟踪和界定。详情也请参阅 Javadoc。
org.hibernate.context.ManagedSessionContext
:当前会话通过当前执行的线程来跟踪和界定。但是,你需要负责使用这个类的静态方法将 Session
实例绑定、或者取消绑定,它并不会打开(open)、flush 或者关闭(close)任何 Session
。
The first two implementations provide a "one session - one database transaction" programming model. This is also known and used as session-per-request. The beginning and end of a Hibernate session is defined by the duration of a database transaction. If you use programmatic transaction demarcation in plain JSE without JTA, you are advised to use the Hibernate Transaction
API to hide the underlying transaction system from your code. If you use JTA, you can utilize the JTA interfaces to demarcate transactions. If you execute in an EJB container that supports CMT, transaction boundaries are defined declaratively and you do not need any transaction or session demarcation operations in your code. Refer to 第 12 章 事务和并发 for more information and code examples.
hibernate.current_session_context_class
配置参数定义了应该采用哪个 org.hibernate.context.CurrentSessionContext
实现。注意,为了向下兼容,如果未配置此参数,但是存在 org.hibernate.transaction.TransactionManagerLookup
的配置,Hibernate 会采用org.hibernate.context.JTASessionContext
。一般而言,此参数的值指明了要使用的实现类的全名,但那三种内置的实现可以使用简写,即 "jta"、"thread" 和 "managed"。
版权 © 2004 Red Hat, Inc.