`

hibernate体系结构

阅读更多

一个非常简要的Hibernate体系结构的概要图:

这个图可以看出,Hibernater使用数据库和配置信息来为应用程序提供持久化服务(以及持久的对象)。

我们来更详细地看一下Hibernate运行时体系结构。由于Hibernate非常灵活,且支持数种应用方案, 所以我们这只描述一下两种极端的情况。“轻型”的体系结构方案,要求应用程序提供自己的JDBC 连接并管理自己的事务。这种方案使用了Hibernate API的最小子集:

“全面解决”的体系结构方案,将应用层从底层的JDBC/JTA API中抽象出来,而让Hibernate来处理这些细节。
图中各个对象的定义如下:
SessionFactory (org.hibernate.SessionFactory)

针对单个数据库映射关系经过编译后的内存镜像,它也是线程安全的(不可变)。 它是生成Session的工厂,本身要用到ConnectionProvider。 该对象可以在进程或集群的级别上,为那些事务之间可以重用的数据提供可选的二级缓存。

Session (org.hibernate.Session)

表示应用程序与持久储存层之间交互操作的一个单线程对象,此对象生存期很短。 其隐藏了JDBC连接,也是Transaction的工厂。 其会持有一个针对持久化对象的必选(第一级)缓存,在遍历对象图或者根据持久化标识查找对象时会用到。

持久的对象及其集合

带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。 这些对象可以是普通的JavaBeans/POJO,唯一特殊的是他们正与(仅仅一个)Session相关联。 这个Session被关闭的同时,这些对象也会脱离持久化状态,可以被应用程序的任何层自由使用。 (例如,用作跟表示层打交道的数据传输对象data transfer object。)

瞬态(transient)以及脱管(detached)的对象及其集合

持久类的没有与Session相关联的实例。 他们可能是在被应用程序实例化后,尚未进行持久化的对象。 也可能是因为实例化他们的Session已经被关闭而脱离持久化的对象。

事务Transaction (org.hibernate.Transaction)

(可选的)应用程序用来指定原子操作单元范围的对象,它是单线程的,生存期很短。 它通过抽象将应用从底层具体的JDBC、JTA以及CORBA事务隔离开。 某些情况下,一个Session之内可能包含多个Transaction对象。 尽管是否使用该对象是可选的,但是事务边界的开启与关闭(无论是使用底层的API还是使用Transaction对象)是必不可少的。

ConnectionProvider (org.hibernate.connection.ConnectionProvider)

(可选的)生成JDBC连接的工厂(同时也起到连接池的作用)。 它通过抽象将应用从底层的DatasourceDriverManager隔离开。 仅供开发者扩展/实现用,并不暴露给应用程序使用。

TransactionFactory (org.hibernate.TransactionFactory)

(可选的)生成Transaction对象实例的工厂。 仅供开发者扩展/实现用,并不暴露给应用程序使用。

扩展接口

Hibernate提供了很多可选的扩展接口,你可以通过实现它们来定制你的持久层的行为。 具体请参考API文档。

 

在一个“轻型”的体系结构中,应用程序可能绕过 Transaction/TransactionFactory 以及 ConnectionProvider 等API直接跟JTA或JDBC打交道。

JMX是管理Java组件(Java components)的J2EE规范。 Hibernate 可以通过一个JMX标准服务来管理。 在这个发行版本中,我们提供了一个MBean接口的实现,即 org.hibernate.jmx.HibernateService

想要看如何在JBoss应用服务器上将Hibernate部署为一个JMX服务的例子,您可以参考JBoss用户指南。 我们现在说一下在Jboss应用服务器上,使用JMX来部署Hibernate的好处:

  • Session管理: Hibernate的Session对象的生命周期可以 自动跟一个JTA事务边界绑定。这意味着你无需手工开关Session了, 这项 工作会由JBoss EJB 拦截器来完成。你再也不用担心你的代码中的事务边界了(除非你想利用Hibernate提供 的Transaction API来自己写一个便于移植的的持久层)。 你现在要通过 HibernateContext来操作Session了。

  • HAR 部署: 通常情况下,你会使用JBoss的服务部署描述符(在EAR或/和SAR文件中)来部署Hibernate JMX服务。 这种部署方式支持所有常见的Hibernate SessionFactory的配置选项。 不过,你需在部署描述符中,列出你所有的映射文件的名字。如果你使用HAR部署方式, JBoss 会自动探测出你的HAR文件中所有的映射文件。

这些选项更多的描述,请参考JBoss 应用程序用户指南。

将Hibernate以部署为JMX服务的另一个好处,是可以查看Hibernate的运行时统计信息。参看 第 4.4.6 节 “ Hibernate的统计(statistics)机制 ”.

在应用程序中,用来实现业务问题实体的(如,在电子商务应用程序中的Customer和Order) 类就是持久化类。不能认为所有的持久化类的实例都是持久的状态——一个实例的状态也可能 是瞬时的或脱管的。

如果这些持久化类遵循一些简单的规则,Hibernate能够工作得最好,这些规则被称作, 简单传统Java对象(POJO:Plain Old Java Object)编程模型。但是这些规则没有一个是必需的。 实际上,Hibernate3对于你的持久化类几乎不做任何设想。你可以用其他的方法来表达领域模型: 比如,使用Map实例的树型结构。

大多数Java程序需要用一个持久化类来表示猫科动物。

package eg;
import java.util.Set;
import java.util.Date;
public class Cat {
private Long id; // identifier
private Date birthdate;
private Color color;
private char sex;
private float weight;
private int litterId;
private Cat mother;
private Set kittens = new HashSet();
private void setId(Long id) {
this.id=id;
}
public Long getId() {
return id;
}
void setBirthdate(Date date) {
birthdate = date;
}
public Date getBirthdate() {
return birthdate;
}
void setWeight(float weight) {
this.weight = weight;
}
public float getWeight() {
return weight;
}
public Color getColor() {
return color;
}
void setColor(Color color) {
this.color = color;
}
void setSex(char sex) {
this.sex=sex;
}
public char getSex() {
return sex;
}
void setLitterId(int id) {
this.litterId = id;
}
public int getLitterId() {
return litterId;
}
void setMother(Cat mother) {
this.mother = mother;
}
public Cat getMother() {
return mother;
}
void setKittens(Set kittens) {
this.kittens = kittens;
}
public Set getKittens() {
return kittens;
}
// addKitten not needed by Hibernate
public void addKitten(Cat kitten) {
kitten.setMother(this);
kitten.setLitterId( kittens.size() );
kittens.add(kitten);
}
}

这里要遵循四条主要的规则:

如果你有如下需求,你必须重载 equals()hashCode()方法:

  • 想把持久类的实例放入Set中(当表示多值关联时,推荐这么做)

  • 想重用脱管实例

Hibernate保证,持久化标识(数据库的行)和仅在特定会话范围内的Java标识是等值的。因此,一旦 我们混合了从不同会话中获取的实例,如果我们希望Set有明确的语义,我们必 须实现equals()hashCode()

实现equals()/hashCode()最显而易见的方法是比较两个对象 标识符的值。如果值相同,则两个对象对应于数据库的同一行,因此它们是相等的(如果都被添加到 Set,则在Set中只有一个元素)。不幸的是,对生成的标识不能 使用这种方法。Hibernate仅对那些持久化对象赋标识值,一个新创建的实例将不会有任何标识值。此外, 如果一个实例没有被保存(unsaved),并且在一个Set中,保存它将会给这个对象 赋一个标识值。如果equals()hashCode()是基于标识值 实现的,则其哈希码将会改变,违反Set的契约。建议去Hibernate的站点看关于这个 问题的全部讨论。注意,这不是一个Hibernate问题,而是一般的Java对象标识和相等的语义问题。

我们建议使用业务键值相等(Business key equality)来实现equals()hashCode()。业务键值相等的意思是,equals()方法 仅仅比较来自业务键的属性,一个业务键将标识在真实世界里(一个天生的候选键) 的实例。

public class Cat {
...
public boolean equals(Object other) {
if (this == other) return true;
if ( !(other instanceof Cat) ) return false;
final Cat cat = (Cat) other;
if ( !cat.getLitterId().equals( getLitterId() ) ) return false;
if ( !cat.getMother().equals( getMother() ) ) return false;
return true;
}
public int hashCode() {
int result;
result = getMother().hashCode();
result = 29 * result + getLitterId();
return result;
}
}

注意,业务键不必是象数据库的主键那样是固定不变的(参见第 12.1.3 节 “关注对象标识(Considering object identity)”)。 对业务键而言,不可变或唯一的属性是好的候选。

注意,以下特性在当前是基于实验考虑的,可能会在将来改变。

运行期的持久化实体没有必要象POJO类或JavaBean对象一样表示。Hibernate也支持动态模型 (在运行期使用MapMap)和象DOM4J的树模型那 样的实体表示。使用这种方法,你不用写持久化类,只写映射文件就行了。

Hibernate默认工作在普通POJO模式。你可以使用配置选项default_entity_mode, 对特定的SessionFactory,设置一个默认的实体表示模式。 (参见表 4.3 “ Hibernate配置属性 ”。)

下面是用Map来表示的例子。首先,在映射文件中,要声明 entity-name来代替(或外加)一个类名。

<hibernate-mapping>
<class entity-name="Customer">
<id name="id"
type="long"
column="ID">
<generator class="sequence"/>
</id>
<property name="name"
column="NAME"
type="string"/>
<property name="address"
column="ADDRESS"
type="string"/>
<many-to-one name="organization"
column="ORGANIZATION_ID"
class="Organization"/>
<bag name="orders"
inverse="true"
lazy="false"
cascade="all">
<key column="CUSTOMER_ID"/>
<one-to-many class="Order"/>
</bag>
</class>
</hibernate-mapping>

注意,虽然是用目标类名来声明关联的,但是关联的目标类型除了是POJO之外,也可以 是一个动态的实体。

在使用dynamic-mapSessionFactory 设置了默认的实体模式之后,可以在运行期使用MapMap

Session s = openSession();
Transaction tx = s.beginTransaction();
Session s = openSession();
// Create a customer
Map david = new HashMap();
david.put("name", "David");
// Create an organization
Map foobar = new HashMap();
foobar.put("name", "Foobar Inc.");
// Link both
david.put("organization", foobar);
// Save both
s.save("Customer", david);
s.save("Organization", foobar);
tx.commit();
s.close();

动态映射的好处是,使原型在不需要实体类实现的情况下,快速转变时间。然而,你无法进行 编译期的类型检查,并可能由此会处理很多的运行期异常。幸亏有了Hibernate映射,它使得数 据库的schema能容易的规格化和合理化,并允许稍后添加正确的领域模型的最新实现。

实体表示模式也能在每个Session的基础上设置:

Session dynamicSession = pojoSession.getSession(EntityMode.MAP);
// Create a customer
Map david = new HashMap();
david.put("name", "David");
dynamicSession.save("Customer", david);
...
dynamicSession.flush();
dynamicSession.close()
...
// Continue on pojoSession

请注意,用EntityMode调用getSession()是在 Session的API中,而不是SessionFactory。 这样,新的Session共享底层的JDBC连接,事务,和其他的上下文信 息。这意味着,你不需要在第二个Session中调用 flush()close(),同样的,把事务和连接的处理 交给原来的工作单元。

关于XML表示能力的更多信息可以在第 19 章 XML映射中找到。

TODO:在property和proxy的包里,用户扩展文件框架。

分享到:
评论

相关推荐

    Hibernate体系结构的概要图

    [Hibernate体系结构的概要图] Hibernate体系结构的概要图 Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。这6个核心接口在任何开发中都会用到。...

    Hibernate 体系结构与工作原理.txt

    Hibernate 体系结构与工作原理.txtHibernate 体系结构与工作原理.txtHibernate 体系结构与工作原理.txt

    hibernate 体系结构与配置 参考文档(html)

    2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 2.5. 上下文相关的(Contextual)Session 3. 配置 3.1. 可编程的配置方式 3.2. 获得SessionFactory 3.3. JDBC...

    电子商务毕业论文

    §1.3.3 Hibernate体系结构 6 §1.4 Hibernate框架 8 §1.4.1 Spring简介 8 §1.4.2 Spring 核心技术 8 §1.4.3 Spring框架结构 9 第2章 系统分析 11 §2.1 系统可行性分析 11 §2.1.1 技术可行性 11 §2.1.2 社会...

    低清版 大型门户网站是这样炼成的.pdf

    4.2.1 hibernate体系结构 196 4.2.2 hibernate api简介 197 4.2.3 配置hibernate 198 4.2.4 hibernate的映射配置文件 201 4.2.5 体验hibernate(会员管理) 203 4.3 hibernate的映射机制 212 4.3.1 hibernate...

    J2EE应用开发详解

    313 17.6 常用的JPA注释 316 17.7 小结 318 第18章 Hibernate 319 18.1 Hibernate体系结构 319 18.2 Hibernate核心接口 321 18.3 一个简单的Hibernate例子 321 18.4 详解Hibernate配置文件 325 18.4.1 Hibernate的两...

    软件体系结构实验(07):Hibernate框架.docx

    软件体系结构实验报告

    软件体系结构实验(09):Spring+Hibernate集成.doc

    软件体系结构实验报告

    Hibernate中文参考文档

    HIBERNATE - 符合Java习惯的关系数据库持久化 如果你对Hibernate和对象/关系数据库映射还是个新手,或者甚至...阅读第 2 章 体系结构(Architecture)来理解Hibernate可以使用的环境....................................

    hibernate基础

    主要内容包括Hibernate的基本体系结构、如何使用Java5注解和基于XML的映射文件来表示映射信息,并讨论了HibernateSession对象和HQL的使用。本书结合大量实际代码,力图使读者能够更好地学习并掌握Hibernate的使用。...

    hibernate的java教学代码

    hibernate教学java很好了解hibernate的体系结构

    JavavEE轻量级框架Struts2+Hibernate+Spring整合开发

    JavavEE轻量级框架Struts2+Hibernate+Spring整合开发,附有每章的PPT

    一个Hibernate的简单实例

    此例子只用Hibernate框架开发,是学习Hibernate的不错例子。 里面包含数据库文件\技术工具说明文件\Hibernate结构体系、核心文件和具体的运行过程。适合Java入门者。

    Hibernate+中文文档

    2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 2.5. 上下文相关的(Contextual)Session 3. 配置 3.1. 可编程的配置方式 3.2. 获得SessionFactory 3.3. ...

    《软件设计与体系结构》实验指导书

    实验一 Servlet 实验二 JSP 实验三 Struts2(一) 实验四 Struts2(二) 17 实验五 Ajax 25 实验六 Hibernate 实验七 企业级软件分层模型 实验八 SSH整合

    JavaEE多层架构Struts2+Spring3+Hibernate3+Ajax的整合

    JavaEE多层架构Struts2+Spring3+Hibernate3+Ajax的整合JavaEE多层架构Struts2+Spring3+Hibernate3+Ajax的整合JavaEE多层架构Struts2+Spring3+Hibernate3+Ajax的整合

    hibernate中文参考文档

    2、体系结构 3、SessionFactory配置 4、持久化类 5、O/R Mapping基础 6、集合类映射 7、组件映射 8、继承映射 9、操作持久化数据 10、事务和并行 11、Hibernate查询语言 12、条件查询 13、原生SQL查询 14、性能提升 ...

    hibernate 教程

    体系结构 2.1. 总览 2.2. JMX集成 2.3. JCA支持 3. SessionFactory配置 3.1. 可编程配置方式 3.2. 获取SessionFactory 3.3. 用户自行提供JDBC连接 3.4. Hibernate提供的JDBC连接 3.5. ...

    hibernate3.2中文文档(chm格式)

    2. 体系结构(Architecture) 2.1. 概况(Overview) 2.2. 实例状态 2.3. JMX整合 2.4. 对JCA的支持 2.5. 上下文相关的(Contextual)Session 3. 配置 3.1. 可编程的配置方式 3.2. 获得SessionFactory 3.3. ...

Global site tag (gtag.js) - Google Analytics