hibernate jar包_Hibernate 简化继承映射

学习映射类层次结构的三个易于实现的策略

概述

Hibernate 是一个纯 Java 的对象关系映射和持久性框架,它允许您用 XML 配置文件把普通 Java 对象映射到关系数据库表。使用 Hibernate 能够节约大量项目开发时间,因为整个 JDBC 层都由这个框架管理。这意味着您的应用程序的数据访问层位于 Hibernate 之上,完全是从底层数据模型中抽象出来的。

比起其他类似的对象关系映射技术(JDO、实体 bean、内部开发等),Hibernate 有许多优势:它是免费的、开源的,已经成熟到良好的程度,并得到广泛应用,而且还有一个非常活跃的社区论坛。

要把 Hibernate 集成到现有的 Java 项目,则需要执行以下步骤:

  1. 从 Hibernate 的 Web 站点下载 Hibernate 框架的最新发行版(请参阅 参考资料一节中的链接。)
  2. 把必需的 Hibernate 库(JAR 文件)复制到应用程序的 CLASSPATH。
  3. 创建 XML 配置文件,用它把 Java 对象映射到数据库表。(我们将在本文中描述这个过程。)
  4. 把 XML 配置文件复制到应用程序的 CLASSPATH。

您会注意到,不必修改任何 Java 对象,您就可以支持框架。例如,假设您对 Java 应用程序使用的数据库表做了些修改 —— 例如修改了列名。在修改完表之后,您要做的只是更新对应的 XML 配置文件。 您不需要重新编译任何 Java 代码。

Hibernate 查询语言(HQL)

Hibernate 提供了一个查询语言,叫作 Hibernate 查询语言(HQL),它与 SQL 很相似。如果您喜欢用老式的 SQL 查询,那么 Hibernate 也为您提供了使用它们的机会。但是我们使用的示例只用 HQL。

HQL 用起来相当简单。您会发现所有的关键字都与您熟悉的 SQL 中的关键字类似,例如 SELECT、 FROM和 WHERE。HQL 与 SQL 的差异在于,您不用针对数据模型(即针对表和列等)直接编写查询,而是应该针对 Java 对象,使用 Java 对象的属性和关系编写查询。

清单 1 演示了一个基本的示例。这个 HQL 代码检索 firstName为 “John.” 的所有 Individual。

清单 1. 基本 HQL 查询

SELECT * FROM eg.hibernate.mapping.dataobject.Individual WHERE firstName = "John"

如果想了解更多有关 HQL 语法的内容,那么您可以参阅 Hibernate 的 Web 站点上有关 HQL 的参考材料(请参阅 参考资料,以获得链接)。

XML 配置文件

功能的核心在于 XML 配置文件。这些文件必须存在于应用程序的 CLASSPATH 中。我们把它们放在示例代码包的 config 目录中(您可以从 参考资料下载)。

我们要研究的第一个文件是 hibernate.cfg.xml。它包含与数据源有关的信息(数据库 URL、模式名称、用户名、口令等),以及对包含映射信息的其他配置文件的引用。

其余的 XML 文件允许您把 Java 类映射到数据库表。稍后我再深入介绍这些文件,但重要的是要清楚它们的文件名要遵守 ClassName.hbm.xml 这个模式。

我们的支持示例

在本文中,我们要研究一个基本示例,演示 Hibernate 如何工作,如何良好地运用三个不同策略,利用 Hibernate 进行对象关系映射。我们的示例是一家保险公司使用的应用程序,公司必须保持客户投保的所有产权的法律记录。我们随本文提供了完整的源代码(请参阅 参考资料);这个代码提供了基本功能,您可以根据它构建全功能的应用程序,例如 Web 或 Swing 应用程序。

我们的示例采用了这类应用程序的经典用例。用户提供搜索参数,查找各种类型的客户(个人、公司、政府机构等),然后显示与指定参数匹配的所有客户列表 —— 即使这些客户的类型不同。用户可以访问同一列表中的某一特定客户更加详细的视图。

在我们的应用程序中,产权由 Right类表示。 Right可以是 Lease 也可以是 Property。 Right由客户所有。为了表示我们的客户,我们要使用通用类 Person。 Person即可以是 Individual也可以是Corporation。当然,保险公司必须知道这些 Right被分配给哪个 Estate。您应当同意, Estate这个术语代表的意义非常泛。所以,我们要用 Land和 Building类给我们的开发人员提供更具体的操作对象。

从这个抽象出发,我们可以开发图 1 所示的类模型:

图 1. 完整的类模型

5621edd67962b496ff500bf40c1db19d.png

我们的数据库模型是为了介绍将在本文中讨论的三个不同策略而设计的。对于 Right层次结构来说,我们要使用一个表( TB_RIGHT),并用 DISCRIMINATOR列映射到正确的类。对于 Person结构,我们要使用一个称为 超表( TB_PERSON)的表,它与另外两个表( TB_CORPORATION和 TB_INDIVIDUAL)共享相同的 ID。第三个层次结构( Estate)使用两个不同的表( TB_BUILDING和 TB_LAND),这两个表通过由两个列( REF_ESTATE_ID和 REF_ESTATE_TYPE)组合定义的外键连接在一起。

图 2 显示了这个数据模型 :

图 2. 完整的数据模型

bca9f813da9c08be21cb251f87b97fb7.png

设置数据库

Hibernate 支持各种各样的 RDBMS,其中任何一种都可以使用我们的示例。但是,本文的示例代码和文本已经针对 HSQLDB(请参阅 参考资料查找链接)进行了调整,这是一个完全用 Java 语言编写的全功能的关系数据库系统。在示例代码包的 sql 目录中,可以找到叫作 datamodel.sql 的文件。这个 SQL 脚本可以创建我们示例中使用的数据模型。

设置 Java 项目

虽然您总能用命令行构建并执行示例代码,但是您可能想在 IDE 中设置项目,以便更好地进行集成。在示例代码包里,您可以找到以下目录:

  • config,包含样本的所有 XML 配置文件(映射、Log4J 等)。
  • data,包含 HSQLDB 使用的配置文件。您还可以找到一个叫作 startHSQLDB.bat 的批处理文件,您可以用它启动数据库。
  • src,包含示例的所有源代码。

请确保把必需的 Java 库和 XML 配置文件复制到应用程序的 CLASSPATH。只需要 Hibernate 和 HSQLDB 库,这些代码就可以正确地编译和运行。您可以从 参考资料一节下载这些包。

策略 1: 每个子类一个表(Persons)

在我们第一个策略中,我们要看看如何映射我们的 Person层次结构。您会注意到,数据模型与我们的类模型非常接近。所以,我们要为层次结构中的每个类采用一个不同的表,但是所有这些表都必须共享相同的主键(我们很快就会详细说明)。Hibernate 在向数据库中插入新记录时,就会使用这个主键。在访问数据库时,它还会利用同一主键执行 JOIN操作。

现在我们需要把对象层次结构映射到表模型。我们有三个表( TB_PERSON、 TB_INDIVIDUAL、和TB_CORPORATION)。前面我们提过,它们都有一个叫作 ID的列,并将该列作为主键。表之间不一定非要有这样的共享列名称,但是这是一个很好的实践 —— 这样做的话,生成的 SQL 查询更容易阅读。

在清单 2 所示的 XML 映射文件中,您会注意到,在 Person的映射定义中,声明了两个具体的 类。XML 元素 映射到顶级表 TB_PERSON的主键,同时 元素(来自每个子类)映射到 TB_INDIVIDUAL的 TB_CORPORATION表中匹配的主键。

清单 2. Person.hbm.xml

<?xml version="1.0" encoding="UTF-8"?>    

保存 Individual的一个新实例,形成我们使用 Hibernate 的 Java 代码非常容易,如清单 3 所示:

清单 3. 保存 Individual 的一个新实例

public Object create(Object object) {  Session session = null;  try {  session = sessionFactory.openSession();  Transaction tx = session.beginTransaction();   session.save(object); session.flush();  tx.commit();  ... }

接着,Hibernate 生成两个 SQL INSERT请求,如清单 4 所示。这两个请求面向的是一个 save()。

清单 4. SQL 插入查询

insert into TB_PERSON (ID) values (?) insert into TB_INDIVIDUAL (FIRST_NAME, LAST_NAME, id) values (?, ?, ?)

要想访问数据库中的 Individual,只需在 HQL 查询中指定类名即可,如清单 5 所示。

清单 5. 调用 HQL 查询

public Person findIndividual(Integer id) {  ...  session.find(  "select p from " + Individual.class.getName() + " as p where p.id = ?
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值