- 浏览: 91725 次
- 性别:
- 来自: 深圳
文章分类
最新评论
一个非常简要的Hibernate体系结构的概要图:
我们来更详细地看一下Hibernate运行时体系结构。由于Hibernate非常灵活,且支持数种应用方案, 所以我们这只描述一下两种极端的情况。“轻型”的体系结构方案,要求应用程序提供自己的JDBC 连接并管理自己的事务。这种方案使用了Hibernate API的最小子集:
针对单个数据库映射关系经过编译后的内存镜像,它也是线程安全的(不可变)。 它是生成Session的工厂,本身要用到ConnectionProvider。 该对象可以在进程或集群的级别上,为那些事务之间可以重用的数据提供可选的二级缓存。
表示应用程序与持久储存层之间交互操作的一个单线程对象,此对象生存期很短。 其隐藏了JDBC连接,也是Transaction的工厂。 其会持有一个针对持久化对象的必选(第一级)缓存,在遍历对象图或者根据持久化标识查找对象时会用到。
带有持久化状态的、具有业务功能的单线程对象,此对象生存期很短。 这些对象可以是普通的JavaBeans/POJO,唯一特殊的是他们正与(仅仅一个)Session相关联。 这个Session被关闭的同时,这些对象也会脱离持久化状态,可以被应用程序的任何层自由使用。 (例如,用作跟表示层打交道的数据传输对象data transfer object。)
持久类的没有与Session相关联的实例。 他们可能是在被应用程序实例化后,尚未进行持久化的对象。 也可能是因为实例化他们的Session已经被关闭而脱离持久化的对象。
(可选的)应用程序用来指定原子操作单元范围的对象,它是单线程的,生存期很短。 它通过抽象将应用从底层具体的JDBC、JTA以及CORBA事务隔离开。 某些情况下,一个Session之内可能包含多个Transaction对象。 尽管是否使用该对象是可选的,但是事务边界的开启与关闭(无论是使用底层的API还是使用Transaction对象)是必不可少的。
(可选的)生成JDBC连接的工厂(同时也起到连接池的作用)。 它通过抽象将应用从底层的Datasource或DriverManager隔离开。 仅供开发者扩展/实现用,并不暴露给应用程序使用。
(可选的)生成Transaction对象实例的工厂。 仅供开发者扩展/实现用,并不暴露给应用程序使用。
Hibernate提供了很多可选的扩展接口,你可以通过实现它们来定制你的持久层的行为。 具体请参考API文档。
在一个“轻型”的体系结构中,应用程序可能绕过 Transaction/TransactionFactory 以及 ConnectionProvider 等API直接跟JTA或JDBC打交道。
一个持久化类的实例可能处于三种不同状态中的某一种。 这三种状态的定义则与所谓的持久化上下文(persistence context)有关。 Hibernate的Session对象就是这个所谓的持久化上下文:
该实例从未与任何持久化上下文关联过。它没有持久化标识(相当于主键)。
实例目前与某个持久化上下文有关联。 它拥有持久化标识(相当于主键),并且可能在数据库中有一个对应的行。 对于某一个特定的持久化上下文,Hibernate保证持久化标识与Java标识(其值代表对象在内存中的位置)等价。
实例曾经与某个持久化上下文发生过关联,不过那个上下文被关闭了, 或者这个实例是被序列化(serialize)到这个进程来的。 它拥有持久化标识,并且在数据库中可能存在一个对应的行。 对于脱管状态的实例,Hibernate不保证任何持久化标识和Java标识的关系。
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); } }
这里要遵循四条主要的规则:
Cat为它的所有持久化字段声明了访问方法。很多其他ORM工具直接对 实例变量进行持久化。我们相信从持久化机制中分离这种实现细节要好得多。 Hibernate持久化JavaBeans风格的属性,认可如下形式的方法名: getFoo, isFoo 和 setFoo。 如果需要,你总是可以切换特定的属性的指示字段的访问方法。
属性不需要要声明为public的。Hibernate默认使用 protected或private的get/set方法对, 对属性进行持久化。
Cat有一个无参数的构造方法。所有的持久化类都必须有一个 默认的构造方法(可以不是public的),这样的话Hibernate就可以使用 Constructor.newInstance()来实例化它们。 我们建议,在Hibernate中,为了运行期代理的生成,构造方法至少是 包(package)内可见的。
Cat有一个属性叫做id。这个属性映射数据库表的主 键字段。这个属性可以叫任何名字,其类型可以是任何的原始类型、原始类型的包装类型、 java.lang.String 或者是 java.util.Date。 (如果你的老式数据库表有联合主键,你甚至可以用一个用户自定义的类,该类拥有这些类型 的属性。参见后面的关于联合标识符的章节。)
标识符属性是可选的。可以不用管它,让Hibernate内部来追踪对象的识别。 不推荐使用这个属性。
实际上,一些功能只对那些声明了标识符属性的类起作用:
-
托管对象的传播性重新(和session)关联(级联更新或级联合并) ——参阅 第 11.11 节 “传播性持久化(transitive persistence)”
-
Session.saveOrUpdate()
-
Session.merge()
我们建议你对持久化类声明命名一致的标识属性。我们还建议你使用一 个可以为空(也就是说,不是原始类型)的类型。
子类也必须遵守第一条和第二条规则。它从超类Cat继承了标识属性。
package eg; public class DomesticCat extends Cat { private String name; public String getName() { return name; } protected void setName(String name) { this.name=name; } }
如果你有如下需求,你必须重载 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也支持动态模型 (在运行期使用Map的Map)和象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-map为SessionFactory 设置了默认的实体模式之后,可以在运行期使用Map的 Map。
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 Validator 实例
2008-06-18 11:21 5689在项目的业务属性中,你是不是要经常验证属性的取值范围呢. 想要 ... -
hibernate Annotations 实例
2008-06-18 11:16 2854从 hbm.xml 到 Annotations 任何获得Ma ... -
HibernateUtilSimple
2008-06-17 10:14 865package org.hibernate.auction.p ... -
HibernateUtil
2008-06-17 10:12 3362package org.hibernate.auction.p ... -
Hibernate的缓存机制介绍
2008-06-16 16:51 918缓存是介于应用程序和 ... -
hibernate常用语句
2008-06-16 16:50 1047Session Session lifecycle begin ... -
hibernate 配置
2008-06-16 16:49 1492第 4 章 配置 由于Hibernate是为了 ... -
对象/关系数据库映射基础
2008-06-16 16:47 1520对象和关系数据库之间的映射通常是用一个XML文档( ... -
集合类(Collections)映射
2008-06-16 16:45 931(译者注:在阅读本章的时候,以后整个手册的阅读过程中,我们都会 ... -
Hibernate包作用详解
2008-06-16 16:43 765Hibernate一共包括了23个ja ... -
HibenateMinute(一)
2008-06-16 16:39 886@ Hibernate3.0 àJBOSS @ ORM à「对 ... -
HibenateMinute(二)
2008-06-16 16:37 1178Criteria: Criteria criteria = s ... -
HibenateMinute(三)
2008-06-16 16:35 880hiberate缓存 一般而言,ORM的数据缓存应包含如下几个 ... -
Hibernate关系映射
2008-06-16 16:34 980第 8 章 关联关系映射 8.1. 介绍 ... -
Hibernate对象共事
2008-06-16 16:32 1063第 11 章 与对象共 ... -
hibernate查询语言
2008-06-16 16:29 2088第 14 章 批量处理(Batch processing ... -
hibernate提升性能
2008-06-16 16:25 971第 20 章 提升性能 20.1. 抓 ... -
hibernate工具箱指南
2008-06-16 16:23 1400第 21 章 工具箱指南 可以通过一系列Eclip ...
相关推荐
[Hibernate体系结构的概要图] Hibernate体系结构的概要图 Hibernate的核心接口一共有6个,分别为:Session、SessionFactory、Transaction、Query、Criteria和Configuration。这6个核心接口在任何开发中都会用到。...
Hibernate 体系结构与工作原理.txtHibernate 体系结构与工作原理.txtHibernate 体系结构与工作原理.txt
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 社会...
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...
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的两...
软件体系结构实验报告
软件体系结构实验报告
HIBERNATE - 符合Java习惯的关系数据库持久化 如果你对Hibernate和对象/关系数据库映射还是个新手,或者甚至...阅读第 2 章 体系结构(Architecture)来理解Hibernate可以使用的环境....................................
主要内容包括Hibernate的基本体系结构、如何使用Java5注解和基于XML的映射文件来表示映射信息,并讨论了HibernateSession对象和HQL的使用。本书结合大量实际代码,力图使读者能够更好地学习并掌握Hibernate的使用。...
hibernate教学java很好了解hibernate的体系结构
JavavEE轻量级框架Struts2+Hibernate+Spring整合开发,附有每章的PPT
此例子只用Hibernate框架开发,是学习Hibernate的不错例子。 里面包含数据库文件\技术工具说明文件\Hibernate结构体系、核心文件和具体的运行过程。适合Java入门者。
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的整合
2、体系结构 3、SessionFactory配置 4、持久化类 5、O/R Mapping基础 6、集合类映射 7、组件映射 8、继承映射 9、操作持久化数据 10、事务和并行 11、Hibernate查询语言 12、条件查询 13、原生SQL查询 14、性能提升 ...
体系结构 2.1. 总览 2.2. JMX集成 2.3. JCA支持 3. SessionFactory配置 3.1. 可编程配置方式 3.2. 获取SessionFactory 3.3. 用户自行提供JDBC连接 3.4. Hibernate提供的JDBC连接 3.5. ...
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. ...