Hibernate In Action
oneGeng
这个作者很懒,什么都没留下…
展开
-
3.4.1 标识和相等
Java的开发者应该明白java对象标识和相等之间的区别。==在Java中代表了两个对象指向Java虚拟机中的同一个区域。 从另一方面讲,对象的相等性实现了equals()方法。它意味着两个不同的对象有着相同的值。就像两个内容一样的字符串的相等代表了它们拥有同样的字符序列,但是在内存的指向却是不同的。 持久化却把这一切搞复杂了。在对象/关系持久化中,一个持久化对象代表了数据库表的某一行翻译 2010-03-17 23:36:00 · 770 阅读 · 2 评论 -
3.7.4 双向关联
到目前为止,一切看起来都工作的很好。但是我们仍然需要能够为特定的item取得所有的bid。这里我们需要一个双向的关联,因此我们需要为Item类添加一些代码: 你可以把addBid()方法当成是在对象模型中实现了一个可管理的关联。 一个基本的one-to-many关联看起来是这样: 元素所定义的类映射是表格BID的一个外键列。注意在前的many-to-one关联映射中,我们翻译 2010-04-15 19:32:00 · 564 阅读 · 0 评论 -
3.7.5 父子关联
在之前的映射中,在Bid和Item之间的关联是一种很松散的状态。在真实的环境中,如果关联的所有试题都有属于其自身的生命周期并且在不相关的业务操作中能被够被创建和删除的话,那么我们将会使用这种映射。特定的关联有着更强的约束;许多实体都是绑定在一起的遗嘱与它们的生命周期无法独立。在我们的例子中,对于item的删除也会将其拥有的所有bids删除。一个bid实例在其生命周期内只能关联到一个item实翻译 2010-04-16 20:39:00 · 602 阅读 · 0 评论 -
3.8 总结
在这一章中,我们把注意力集中到了对象/关系不匹配的方面,并且讨论了ORM中常见的4个问题。我们讨论了持久类的编程模型以及细粒度的Hibernate ORM元数据、对象标识、继承和关联关系。 现在你应该明白在业务模型中的持久类应该是松耦合的,不和诸如事务和安全产生关联。甚至持久相关的东西不应该泄漏到业务模型。我们不再使用那些限制非常多的编程模型如EJB。取而代之的是,我们使用透明持久化,一般翻译 2010-04-19 22:24:00 · 473 阅读 · 0 评论 -
3.6.2 每张表一个类层次
另外一种做法就是一张表映射到整个类层次上面。这张表的列和类层次中的所有属性相对应。具体的子类代表的行有discrimator列来决定。具体可以参看3.8。 在性能和简易性上这种映射策略都是值得考虑的。同时它也是表示多态的最好方法,不论是多态查询还是非多态查询都能工作的很好,而且容易实现。它可以尽可能的不使用连接和联合,schema的改变也变得更加的直观。 有一个主要的问题:表示属性的翻译 2010-04-07 17:32:00 · 533 阅读 · 0 评论 -
3.6.3 每张表一个子类
第三种做法就是使用继承关系来表示外键关系类型。每一个子类都声明持久化属性-甚至包括抽象类和接口,都有自己的表。 与每张表一个具体的类不同,这里表中的列支敦那些非继承过来的属性有效,主键也是父类对应的表的外键。这种方法可以在图3.9中看到。 如果CreditCard类的对象被持久化的话,那么继承自父类BillingDetails的属性被持久化为表BILLING_DETAILS的行。而那翻译 2010-04-08 20:35:00 · 402 阅读 · 0 评论 -
4 使用持久化对象
现在你已经了解了Hibernate和ORM如何解决对象/关系不匹配静态方面的问题。到目前为止,这些知识可以解决那些结构上不匹配的问题了,但是我们需要更多东西来提供更有效率的解决方案。我们必须考虑运行时数据的访问,因为数据访问是程序性能的关键部分。你需要学习如何有效的保存和装载对象。 这一章涵盖了对象/关系不匹配行为方面的问题,在第一节中列出了O/R映射中的后四个问题。这四个问题和在第三章中翻译 2010-04-21 22:52:00 · 437 阅读 · 0 评论 -
3.6.4 选择策略
你可以在抽象类和接口上应用所有的映射策略。接口没有状态,但是包含方法声明,因此可以被当成抽象类来对待。你可以使用、或者来映射接口。同时你也可以使用来映射声明的或者继承的属性。Hibernate并不会实例化抽象类,即使你查询或者加载这些抽象类。 下面是一些规则:如果你不进行多态连接和查询的话,那么使用每张表对应一个具体类的策略。反之,如果你需要进行多态链接和查询并且资历哦的属性又不太多的翻译 2010-04-09 17:29:00 · 405 阅读 · 0 评论 -
4.1 持久化生命周期
因为Hibernate拥有透明的持久化机制——类不需要关系其自身的持久化能力——业务逻辑也无需关心它们操作的是持久化状态还是在内存中的临时状态。应用程序在调用一个对象的方法的时候没有必要去关心其是否被持久化了。 然而,在任何带有持久化状态的程序中,在需要保存对象在内存中的状态到数据库的时候,应用程序都需要和持久层打交道。为了完成这项工作,你可以通过调用Hibernate的持久化管理器(Se翻译 2010-04-22 21:17:00 · 491 阅读 · 0 评论 -
4.1.1 transient对象
在hibernate中,对象通过new来初始化而不是立即持久化。它们的状态是透明的,它们的状态并没有和数据库的数据行关联起来,因此如果它们的引用不存在的话,它们的状态也会消失。在引用不再存在的时候,它们的生命周期也就结束了,它们不再具有可访问性等待被垃圾回收器处理。 Hibernate认为所有transient的对象都是非事务性的;对于transient对象状态的修改不包含在任何事务之中翻译 2010-04-27 19:47:00 · 462 阅读 · 0 评论 -
3.7.3 最简单的关联
从Bid到Item的关联是在ORM中最简单的关联关系。从getItem()方法返回的对象引用可以很容易的映射到BID表的外键列上。首先,先看看Bid的Java实现: 接下来,就是Hibernate中的映射: 这个映射被称为单向的的many-to-one映射。BID表中的ITEM_ID字段是关联到ITEM表主键的外键。 在这里,我们明确的给出了关联指向Item类。但这并不是翻译 2010-04-14 22:51:00 · 401 阅读 · 0 评论 -
3.6 映射类的继承
最简单的映射策略莫过于每个表都映射一个对应的类。这种方法看起来非常简单,而且当你遇到类的继承之前它工作的很好。 在面向对象和关系世界之间,在不匹配的特征方面最明显的就是继承。在面向对象的模型中同时存在is a和has a的关系。而SQL为基础的模型仅仅提供了has a的关系。 有三种不同的方法来表示继承的体系。这在Scott Ambler的“Mapping Objects to Rel翻译 2010-04-01 22:49:00 · 331 阅读 · 0 评论 -
3.6.1
假设我们首先采用最简单的方法:每一张表对应一个类。类当中的所有属性,包括继承的属性,都会映射到表中的列。 这种方法的最大问题就是它不能很好的支持多台的关联。在数据库中,关联通常表现为外键关系。在图3.7中,如果所有的子类被表现为外键关系,那么它们的父类的多台关联并不能被简单的表示成为关联关系。但是这可能会为业务模型带来一些问题,因为父类BillingDetails和User存在关联,那么翻译 2010-04-02 10:46:00 · 563 阅读 · 0 评论 -
3.4.2 数据库标识
在hibernate中,有两种方式来暴露数据库标识:持久化对象的identifier属性通过Session.getIdentifier(Object o)的返回值 identifier属性很特殊,它的值是代表数据库行的主键。在我们的业务模型中,并不经常使用identifier属性,她仅仅是持久-关系相关,并不是业务问题。在我们的范例中,identifier属性经常被命名为id。因此翻译 2010-03-18 22:56:00 · 1416 阅读 · 0 评论 -
3.4.3 选择主键
你需要告诉Hibernate你选择的主键生成策略。但是首先,让我们定义什么是主键。 候选键是唯一能标识数据库的行的键。一个候选键必须满足如下的属性:值不能为空每一行都有一个唯一的值对于特定行来说,其值是稳定的,不改变的 对于给定的表来说,几列或者几列的联合必须满足这些属性。如果一个表拥有一个能够标识行的属性,这就称之为主键。如果同时存在多个候选键,那么你可以从其中选择一个作翻译 2010-03-19 20:51:00 · 733 阅读 · 0 评论 -
3.4 理解对象标识
在讨论数据库标识以及Hibernate如何管理这些标识之前,理解对象标识和对象相等之间的差别非常重要。这些概念对于完成对CaveatEmptor类的映射非常重要。翻译 2010-03-17 23:13:00 · 602 阅读 · 0 评论 -
3.5 细粒度的对象模型
Hibernate的一个主要目标就是支持细粒度的对象模型,细粒度的对象模型也是一个业务模型的一个最重要的需求。这就是我们选择POJOs的原因之一。 从字面上理解,细粒度就意味着比数据库表更多的类。例如,一个用户可能需要一个账单地址和一个家庭地址。在数据库中,我们可能拥有一个USER表,它包括数据列BILLING_STREET,BILLING_CITY,BILLING_ZIPCODE,HOM翻译 2010-03-22 20:52:00 · 647 阅读 · 0 评论 -
3.5.1 实体和值类型
这里给我们展示了一个在ORM中重要的区别。在Java中,所有的类都是等价的:所有的对象都有自己的标识和生命周期,所有类的势力都是通过引用传递。只有原始类型通过值传递。 我们建议设计比数据表更多的持久化类。表中的一行可以由多个对象来表示。因为数据库标识使用主键来表示的,而许多持久化类并不拥有属于自己的标识。因此在一些持久化类中,持久化机制实现了值传递的语义。这些对象的其中一个拥有属于自身的标翻译 2010-03-24 23:05:00 · 614 阅读 · 0 评论 -
3.5.2 使用组件
迄今为止,我们对象模型中的类都有其自身的生命周期和身份标识。但是,User类和Address类之间有一种特殊的关联关系,在图3.5中你会看到。 在对象模型的术语中,关联是关系的一个集合。集合是一个特定类型的关联:它和对象的生命周期关联。在我们的例子中,我们还包括另外一种强类型:组合,它的生命周期依赖于整个的生命周期。 对象模型专家和UML设计者可能会认为在Java实现上,组合和其他弱类翻译 2010-03-30 22:37:00 · 402 阅读 · 0 评论 -
3.7.1 管理关联?
如果你使用过CMP2.0/2.1的话,那么你一定会熟悉管理的关联的概念。CMP关联被称作容器管理的关联。在CMP中的关联都是双向的:关联的一端发生变化,一定也会在关联的另外一端产生反应。举例来说,如果我们调用bid.setItem(item)方法,那么容器会自动调用item.getBids().add(item)。 透明的面向POJO的持久化实现(如Hibernate)并没有实现可管理的关翻译 2010-04-12 22:19:00 · 412 阅读 · 0 评论 -
3.7.2 多样性
在关于关联关系的描述中,我们经常使用多样性。请看图3.10。 对于我们来说,多样性有以下两点说明:对于一个Item来说,是否有多个Bid对应?对于一个Bid来说,是否有多个Item对应? 从我们的对象模型中,可以看出从Bid到Item是多对一的关联关系。考虑到关联的方向性,我们也可以说从Item到Bid是一种一对多的关联关系。 在对象的持久化中,我们并不在“多”的具翻译 2010-04-12 22:50:00 · 375 阅读 · 0 评论 -
3.7 介绍关联
管理类之间的关联和管理表之间的联系都是ORM的灵魂。在ORM的实现中最困难的部分也就是关联的管理。 Hibernate的关联模型很丰富,但是并不是没有缺陷,尤其是对于那些新手来说。在这一部分,我们并不会覆盖到所有的内容。我们会针对一般性的情况来举例。在第六章我们将会对关联的映射有完整的介绍。 但是首先,我们需要先解释一些事情。翻译 2010-04-12 22:12:00 · 307 阅读 · 0 评论 -
4.1.2 持久化对象
持久化实例拥有数据库标识,就像在第三章3.4中讨论的那样。这意味着持久化实例都拥有一个主键作为它的数据库标识符。 持久化实例可能是那些通过程序初始化然后通过调用持久化管理器的save()方法来完成的。然后持久化对象就和持久化管理器产生了关联。持久化对象也可以通过和其他持久化管理器关联的持久化对象引用而来。另外,持久化对象也可以通过查询数据库得来。也就是说,持久化实例通常都和Session产翻译 2010-04-27 20:38:00 · 405 阅读 · 0 评论 -
4.1.4 对象身份的范围
作为开发人员,我们使用==来识别一个对象的身份。因此,如果一个对象更改了状态以后,它的身份是否仍然和原来一样?在分层的程序当中,可能并不如此简单。 为了更深入探讨这个问题,需要明白在java对象身份和数据库标识之间的关系。有些时候,它们是等价的,而有时它们又不是相等的。我们把这个问题归结为对象身份的范围。 对于这个范围,有三种一般的选择: (1)如果一个持久层没有身份标识的范围的翻译 2010-05-05 22:52:00 · 524 阅读 · 0 评论 -
4.2.5 将持久化对象编程transient状态
最后,你可以把一个detached对象编程transient状态,删除其在数据库中对应的状态。这意味着你不需要重新和session产生关联去从数据库中删除它,你可以直接删除一个detached实例: 在这个例子中,delete()方法做了两件事情:重新和session关联,执行删除。翻译 2010-05-12 21:49:00 · 397 阅读 · 0 评论 -
4.3.4 区分transient和detached实例
因为Hibernate并不会保存指向detached实例的引用,你应该让Hibernate知道如何区分detached实例(laptops)和transient实例(laptopBags)。 如果Hibernate认为实例是一个未保存的transient的实例的话,那么: 1)标识符为null(如果存在的话) 2)version属性为null(如果存在的话) 3)在映射文档中设翻译 2010-05-18 22:32:00 · 509 阅读 · 0 评论 -
4.4.1 通过标识符取得对象
下面的代码片段展示了如何从数据库中取得对象: User user=(User)session.get(User.class,userID); get()方法比较特殊,因此标识符唯一的指定了一个类的实例。因此,对于程序来说,使用标识符是处理持久化对象的一种常用手段。通过标识符取得对象还可以利用缓存,这样可以减少访问数据库的次数。 Hibernate同时也提供了load()方法:翻译 2010-05-19 20:43:00 · 503 阅读 · 0 评论 -
4.4.2 HQL介绍
HQL是一种面向对象的查询语言,其格式与SQL类似。HQL和ODMG的OQL以及EJB-QL类似,但是与OQL不同的是,它用在SQL数据库的环境中,而且提供了比EJB-QL更强大的功能。只要你有一点SQL的基础就能很容易的学习HQL。HQL并不像SQL那样是一种获取数据的语言。它用来获取对象,而不是更新或者插入或者删除。对象状态的同步是持久化管理器的功能而不是开发者的。大部分时间翻译 2010-05-20 20:49:00 · 435 阅读 · 0 评论 -
4.4 得到对象
从数据库中取得持久化对象是Hibernate中最有趣的一项工作。针对这种需求,Hibernate提供了以下几种方法: 1)通过已经取得持久化对象,使用它们的getter方法。Hibernate会自动的装载对象图的节点,当前前提是Session还未被关闭。 2)通过标识符取得。 3)通过HQL。 4)使用Criteria API。 5)使用SQL。 在你的Hibernat翻译 2010-05-19 20:14:00 · 385 阅读 · 0 评论 -
4.4.3 通过Criteria查询
Hibernate QBC(query by criteria)允许你在运行时通过包装一个标准的对象来构建查询。这种方式可以允许你动态的指定一些约束,但是同时它也丧失了HQL的一些易用性。从另一方面说,通过Criteria构建的查询的可读性比HQL更差。一个Criteria是一组Criterion实例组成的树。Express类提供了静态的工厂类方法来返回Criterion实例。一翻译 2010-05-21 20:54:00 · 448 阅读 · 0 评论 -
4.4.4 通过实例查询
作为QBC工具的一部分,Hibernate支持QBE(query by example)。QBE的意图在于它支持通过一些特定的属性来执行查询。查询的结果返回所有具有匹配属性的实例。QBE并不是一种特别的方法,但是在某些程序中它很有用。下面的代码片段描述了一个Hibernate QBE:QBE的一个典型应用就是通过属性匹配返回结果。而这通过查询语言则很难完成。QBC以及QBE会翻译 2010-05-21 21:16:00 · 438 阅读 · 0 评论 -
4.4.5 取得策略
在传统的关系数据库访问中,你可以通过一条SQL语句,利用内连接和外连接来取得所需要的数据。对于一些原始的ORM实现策略来说,访问对象图的持久化对象需要对数据库进行许多琐碎的请求才行。这种方式没有充分的利用关系数据库连接的能力。实际使用中,这种策略的性能很差。ORM中需要处理的最难的问题,就是如何有效的访问关系型数据。鉴于我们处理过的多个应用来说,通过对数据库频繁访问的方式来取得数据库是不可翻译 2010-05-24 20:58:00 · 456 阅读 · 0 评论 -
4.4.6 在映射中选择加载策略
Hibernate允许在元数据中指定默认的关联加载策略。你可以通过重写Hibernate查询方法来修改默认的策略。这里有个小建议:你不需要立即理解所有的选项;我们建议先整体浏览这部分的内容,在以后的程序可以作为参考。在Hibernate的映射中,集合的映射和普通对象的映射有不同的地方,所以,将分别来讨论这两种情况。首先来考虑Bid和Item之间的双向关联。单点关联对于或者关联来说翻译 2010-05-25 18:57:00 · 700 阅读 · 0 评论 -
4.2.3 重新获得持久化对象
Session也通常被用来查询来获得一个持久化对象。Hibernate在这方面的功能尤其强大,在下面的章节你会看到。然而,SessionAPI提供了一个简单的查询:通过标识符来查询。其中的一个方法就是get(): 取得的对象作为一个detached对象存在。当然如果没有数据行对应的话,那么get()方法返回null。翻译 2010-05-11 20:26:00 · 366 阅读 · 0 评论 -
4.3.1 通过可达性完成持久化
如果说一个持久层实现了持久化的可达性的话,那么从一个已经持久化了的对象创建另外一个新的对象时,那个新的对象也会被持久化。在图4.2中展示了这种行为。 在这个例子中,“Computer”是一个持久化对象。“Desktop Pcs”和“Monitors”也是持久化的;可以通过“Computer”来访问到它们。“Electronics”和“Cell Phones”是transient的。注翻译 2010-05-13 20:37:00 · 478 阅读 · 0 评论 -
4.2 持久化管理器
任何一个透明化的持久化工具都会提供一个持久化管理器的API,它通常能够给提供如下服务: 1)基本的CRUD操作 2)查询操作 3)事务控制 4)事务级别缓存的管理 持久化管理器能够通过几个不同的接口来暴露给开发者。这些接口的底层实现都紧密相连。 在应用程序和Hibernate最核心的接口是Session;它是你所有操作的起点。在本书的其余部分,持久化管理器和Sessi翻译 2010-05-11 19:29:00 · 517 阅读 · 0 评论 -
4.1.5 对象身份标识范围之外
如果一个对象引用离开了对象身份的范围,那么我们称这个引用指向了一个detached对象。为了这个概念如此有用呢? 在web程序中,通常在用户交互中你不需要维护一个数据库事务。用户可能需要花费很长时间去做修改方面的事情,但是由于性能方面的原因,你必须保证数据库事务不能占用太长时间并且尽快释放数据库资源。在这个环境中,重用一个指向detached实例的应用就变得很有意义。例如,你可能想要发送一翻译 2010-05-07 21:15:00 · 456 阅读 · 0 评论 -
4.1.6 实现equals()和hashCode()
在java中,equals()方法通常被应用程序调用或者被集合调用。例如,Set会调用equals()方法来确定元素是否重复。 首先,我们来考虑equals()的默认实现。Hibernate保证在每个Session中,每个表格行有且只有一个对象与其对应。如果你没有从其他的Session中取得对象的话,那么默认的equals方法应该是有效的。一旦你拥有被多个Session共享的对象的话,那翻译 2010-05-10 19:47:00 · 463 阅读 · 0 评论 -
4.2.1 持久化一个对象
你想做的第一件事就是用Session把一个Transient对象持久化。为了做到这些,你需要使用save()方法: 首先,我们初始化一个user对象。当然,我们也可以在建立Session实例之后再初始化它,它们之间的顺序没有什么关系。通过SessionFactory来获得一个Session的实例,然后我们开始一个新事务。 通过调用save()方法把transient对象持久化翻译 2010-05-11 20:07:00 · 635 阅读 · 0 评论 -
4.2.6 将detached对象编程transient状态
最后,你可以把一个detached对象编程transient状态,删除其在数据库中对应的状态。这意味着你不需要重新和session产生关联去从数据库中删除它,你可以直接删除一个detached实例: 在这个例子中,delete()方法做了两件事情:重新和session关联,执行删除。翻译 2010-05-12 22:00:00 · 387 阅读 · 0 评论