Hibernate和Spring是两个杰出的开源框架,它们在越来越多的J2EE应用中得到采用。尽管它们致力于解决的问题有很大区别,它们却都有一个重要特性:依赖注入。Spring有助于在将对象返回给客户端之前整理出对象之间的依赖关系,从而大大减少客户端的编码。而Hibernate则擅长于在将整个对象模型返回给客户端之前整理出数据模型所表现的依赖关系。当直接使用JDBC将数据模型映射为对象模型时,我们通常需要编写大量的代码以构建对象模型。而Hibernate消除了其中的大部分编码工作。
Hibernate 2.x提供了基本的表格到对象的映射、常见的关联映射(包括一对一、一对多和多对多关联)、多态映射等等。Hibernate 3.x则通过使用formula、filter、subselect等提高映射灵活性,提供细粒度的解释特性,从而将其推进到一个新的级别。
在本文中,我们将展示有助于模型转换的各种formula特性。在Hibernate 3.x之前,formula属性只能够出现在property元素中。现在仍然可以这样做,但是Hibernate 3.x提供了一个formula属性或元素(两者在formula的用法方面实质上是等效的),可以在许多元素中使用,包括discriminator、many-to-one、one-to-one、element、many-to-many、map-key、map-key-many-to-many和property。这样就大大提高了对象关系映射的灵活性,从而支持对复杂数据模型的更为细粒度的解释。
基本上,有两种情况必须使用formula:
需要formula的计算结果时。与元素discriminator、element、map-key、map-key-many-to-many和property一起使用formula属于这类情况。
为了连接的目的需要使用formula时。与元素many-to-one、one-to-one和many-to-many一起使用formula属于这类情况。
第一类:从formula获取计算结果 Discriminator(识别器)
在现实数据模式中,经常出现使用一个表来描述另一个表的情况。在对象关系映射中,Formula有助于提供灵活的多态性。
在图1展示的例子中,有两个表:Product和ProductRelease。每个产品记录有一个ProductReleaseID来引用它对应的产品版本记录,包括产品版本名称、类型、版本日期等。
Product and Product Release Data Model
图1. 产品和产品版本数据模型
在ProductRelease表中有一个值得注意的属性是SubProductAllowable,它的值可以是0或1。值为1意味着允许该产品版本中的任何产品有子产品,而值为0则意味着不允许有子产品。例如,有些产品由多个子产品组成,而有些产品只有该产品本身。
图2展示了一个对该数据模型解释而成的对象模型。Nested接口定义了getSubProducts和setSubProducts方法。NestedProduct类扩展了基类Product并实现了Nested接口。一个产品数据记录应该是Product还是NestedProduct取决于相应产品版本记录的SubProductAllowable值。
Product and Product Release Object Domain Model
图2. 产品和产品版本对象的域模型
为了完成这个模型转换,我们使用了Hibernate 3.x映射,如下:
<hibernate-mapping>
<class name="Product"
discriminator-value="0" lazy="false">
<id name="id" type="long"/>
<discriminator
formula="(select pr.SubProductAllowable
from ProductRelease pr
where pr.productReleaseID=
productReleaseID)"
type="integer" />
<subclass name="NestedProduct"
discriminator-value="1"/>
</class>
</hibernate-mapping>
如果formula表达式计算结果为0,也就是不支持子产品,则对象将属于Product类。如果结果是1,对象将是一个NestedProduct。在表1和表2中,对Product表中的第一个记录(ProductID=10000001)来说,初始化的类将是NestedProduct,因为它引用一个SubProductAllowable=1的ProductRelease记录。对Product表中的第二个记录(ProductID=20000001)来说,初始化的类将是Product,因为它引用一个SubProductAllowable=0的ProductRelease记录。
S/N ProductReleaseID SubProductAllowable ...
1 11 1 i
2 601 0 i
. ProductRelease表中的记录
S/N ProductID ProductReleaseID ...
1 10000001 11 i
2 20000001 601 ...
表 2. Product表中的记录
Property
Property元素中的formula允许对象属性包含导出值,比如sum、average、max等的结果。如:
<property name="averagePrice" formula="(select avg(pc.price) from PriceCatalogue pc, SelectedItems si where si.priceRefID=pc.priceID)"/>
此外,formula还可以基于当前记录的特定属性值从另一个表检索值。例如:
<property name="currencyName" formula="(select cur.name from currency cur where cur.id= currencyID)"/>
它从currency表检索货币名称。如您所见,这些直接的映射可以消除大量的转换编码。
map-key
formula允许map-key取任何可能的值。在下面的例子中(图3),我们希望Role_roleID成为对象模型的map-key(图4)。
User Role Data Schema
图3. 用户角色数据模式
User Role Object Model
图4. 用户角色对象模型
在上面的数据模式中,User和Role被通过一个称为User_has_Role的多对多的关系表连接起来。为了获取一个User以及分配给它的所有角色,我们使用下面的映射:
<hibernate-mapping>
<class name="User">
<id name="userID"/>
<map name="roles"
table="UserRole"/>
<key column="User_userID"/>
<map-key
formula="Role_RoleID"
type="string"/>
<many-to-many
column="Role_RoleID"
class="Role"/>
</map>
</class>
<class name="Role">
<id name="roleID"/>
</class>
</hibernate-mapping>
Role_RoleID用作many-to-many元素的连接列值。然而,Hibernate不允许map-key和many-to-many的column属性同时使用Role_RoleID。但是使用一个formula,Role_RoleID还是可以用于map-key。
Formula和map-key-many-to-many的用法与map-key类似。然而,map-key-many-to-many通常用于三重关联,其中map键是被引用的对象自身,而不是一个被引用的属性。
然而,有些地方不支持formula。有些数据库(如Oracle 7)不支持嵌入的select语句(即,嵌入一个SQL语句的select部分中的selectSQL),也不支持用于计算结果的formula。因此,需要首先检查是否支持嵌入式的selectSQL语句。
因为由Hibernate映射生成的SQL将formula表达式作为其select目标的一部分,所以对所使用的数据库的非标准语言将有助于充分使用formula,尽管这可能会降低代码的可移植性。
第二类:将formula用于连接 many-to-one
现实世界数据模型中的另一个常见场景是私有关系映射,它是指除基本的一对一、一对多和多对多关系之外的映射。formula是针对这种私有关系管理所提供的元素之一。图5展示了一个例子,其中一个公司可以有多个联系人,但是他们之中只能有一个是默认的联系人。一个公司有多个联系人是典型的一对多关系。但是,为了标识默认联系人,ContactPerson表使用了一个defaultFlag属性(1为是,0为否)。
图5. 用户角色数据模式
图6. 用户角色对象模型
为了将默认联系人关系解释为对象模型(图6),我们使用下面的映射:
<hibernate-mapping>
<class name="Company" table="Company">
<id name="id" />
<many-to-one
name="defaultContactPerson"
property-ref="defaultContactPerson">
<column name="id"/>
<formula>1</formula>
</many-to-one>
</class>
<class name="Person" >
<id name="id" />
<properties name="defaultContactPerson">
<property name="companyID" />
<property name="defaultFlag" />
</properties>
</class>
</hibernate-mapping>
我们将companyID和defaultFlag聚合到一个名为defaultContactPerson的properties元素中,形成Person表的一个独有的键。将Company类中的many-to-one元素与Person类中的defaultContactPersonproperties元素连接。产成的SQL将类似于:
select c.id, p.id from Company c, Person p where p.companyID=c.id and p.defaultFlag=1
one-to-one
在Hibernate中,one-to-one主要用于两个表共用相同的主键。而对于外键关联,通常使用many-to-one。但是,使用formula,one-to-one可以通过外键连接多个表。上面的many-to-one例子可以使用one-to-one映射为:
<hibernate-mapping>
<class name="Company" table="Company" >
<id name="id" />
<one-to-one name="defaultContactPerson"
property-ref="defaultContactPerson" >
<formula>id</formula>
<formula>1</formula>
</many-to-one>
</class>
<class name="Person" >
<id name="id" />
<properties name="defaultContactPerson">
<property name="companyID" />
<property name="defaultFlag" />
</properties>
</class>
</hibernate-mapping>
其他:many-to-many
formula可以与many-to-many元素一起用于从关系表到实体表的特殊连接,尽管通常不需要这样做。
结束语
本文中的例子展示了大部分的formula使用场景。当需要formula的计算值时,formula表达式将出现在产生的SQL语句的select部分。而当formula用于连接时,它出现在产生的SQL语句的where部分。此外,formula表达式可以使用任意的SQL非标准语言,只要目标数据库支持。因此,formula有助于无需编码地实现从数据模型到对象模型的细粒度映射。
分享到:
相关推荐
### Hibernate原理详细解说 #### Hibernate概述 Hibernate 是一个开源的对象关系映射(Object Relational Mapping,简称 ORM)框架,用于 Java 应用程序与关系型数据库之间的交互。它通过将对象模型与数据库模型...
Hibernate merge 使用详情解说 在 Hibernate 中,merge 方法是非常重要的一个方法,它能够帮助开发者轻松地处理数据的更新和插入操作。那么,merge 方法到底如何工作的呢?下面,我们将对 merge 方法进行详细的解释...
轻量级javaee 企业应用于实践 有专业教授现场演示 内容和清晰 态度亲切 不可或缺
hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,hibernate,包含4个说明文档,分别详细解说了hibernate关联映射的...
### Hibernate详解 #### 一、什么是ORM以及Hibernate ORM(Object-Relational Mapping,对象关系映射)...同时,Hibernate还提供了丰富的API支持复杂的数据查询和事务管理,是现代Java应用程序开发不可或缺的一部分。
2. 支持复杂查询:除了HQL和Criteria API,Hibernate还支持原生SQL查询,以处理更复杂的查询需求。 3. 数据缓存:通过二级缓存机制,提高数据访问效率,减少对数据库的直接访问。 4. 支持事务:提供了事务管理和...
Hibernate 配置各种数据库 Hibernate 是一个基于 Java 的持久层框架,提供了一个抽象的数据访问层,能够与多种数据库进行集成。在 Hibernate 的配置文件中,我们可以配置不同的数据库连接,包括驱动程序、URL 等...
Hibernate是一个开源的对象关系映射(ORM)框架,它封装了JDBC(Java Database Connectivity)的复杂性,并允许Java开发者以面向对象的方式操作数据库。Hibernate框架被广泛应用于企业级Java应用程序中,可以与...
Hibernate AIP,全称为Hibernate Application Integration Process,是Java开发领域中使用Hibernate框架进行应用程序集成的一种实践过程。Hibernate作为一款强大的对象关系映射(ORM)工具,极大地简化了Java应用...
总的来说,Hibernate是Java开发中的重要工具,它通过ORM解决了数据库操作的复杂性,提供了更高级别的抽象。理解和熟练使用Hibernate配置、异常处理、HQL查询以及IDE集成是每个Java开发者必备的技能。通过上述步骤,...
此外,还有Criteria API和HQL(Hibernate Query Language)用于复杂查询。 6. **事务管理**: 在Hibernate中,事务处理是通过Session的beginTransaction()、commit()和rollback()方法实现的。了解事务的ACID特性...
然而,为了满足更复杂的业务需求,Hibernate还提供了丰富的扩展功能,这就是我们今天要讨论的Hibernate-Extensions。这个完整的安装包,包含了一系列强大的工具和功能,旨在提升开发效率,优化数据管理。 一、...
- Native SQL:直接执行SQL查询,适用于Hibernate无法满足的复杂场景。 - Criteria API:动态构建查询,无需预先编写查询字符串。 十、JPA支持 Hibernate 3.2增加了对Java Persistence API(JPA)的支持,使得...
此外,Hibernate3提供了强大的关联映射功能,如一对一、一对多、多对一和多对多关系,使得处理复杂的数据库关系变得简单。 总的来说,Hibernate3是一个功能强大的ORM工具,简化了Java应用程序与数据库的交互,提高...
8. **关联映射**:Hibernate支持一对一、一对多、多对一、多对多等各种关联关系的映射,方便地处理复杂的数据库关系。 9. **事件监听器**:通过事件监听机制,开发者可以在特定操作(如对象的保存、更新或删除)...
5. **查询语言**:Hibernate提供了强大的查询语言HQL(Hibernate Query Language),用于执行复杂的数据库查询操作。 6. **高级特性**:除了基础功能之外,本书还涵盖了诸如懒加载、批量更新和删除等高级特性。 ###...
Hibernate提供了丰富的API和配置选项,比如通过XML或注解定义实体类,配置数据源,使用HQL(Hibernate Query Language)或JPQL(Java Persistence Query Language)进行复杂查询,以及事务管理和缓存策略等。...
《Hibernate 3.6 中文 CHM》是一个针对Hibernate 3.6版本的详细使用指南,旨在帮助开发者理解和掌握这个强大的...通过深入学习和实践,开发者可以充分利用Hibernate的强大功能,提高开发效率,降低数据库操作的复杂性。
它的目标是减少数据库访问的复杂性,提高开发效率。 2. **核心组件**: - **hibernate-core.jar**:这是Hibernate的核心库,包含了用于对象关系映射、查询语言、事务处理等的基本类和接口。 - **hibernate-...
在处理复杂的数据映射时,Hibernate展现出了其独特的魅力。 ### 复杂数据映射的概念 在现实世界的应用中,数据模型往往包含了多种复杂的关联关系,如一对一、一对多以及多对多。这些关系在数据库设计中通常表现为...