|
引言
让我们面对现实吧,如果您在企业应用程序中以手工方式编写 SQL 语句的代码,那么您将花费大量的开发时间去更新和维护持久性层。要是能够方便地将现有 Java™ 对象持久保存到关系数据库(如 IBM® DB2® Universal Database™,UDB)岂不是很好?
幸运的是存在这样的办法。对象/关系(ObjectRelational,OR)映射工具是一些成熟的工具,它们能够将对象映射到关系数据库中的行,从而不再需要复杂的持久层,并且使开发人员只需编写最少的 SQL,在多数情况下不需编写任何 SQL。
Hibernate 是按照 LGPL 许可证发布的开放式源代码应用程序,它是“用于 Java 的超高性能的对象/关系持久性和查询服务”。在本文中,我们将为您说明如何使用 Hibernate 方便地(一行 SQL 代码都不用写)将 Java 对象持久保存到 DB2 数据库中。
为了演示 Hibernate 的工作机制,我们将创建一个简单的类模型,它由两个类组成:Employee 和 Department。为了简单起见,一名员工(employee)有一个部门(department),而部门没有到员工的引用。有关类图参阅图 1。
图 1. EmployeeDepartment 类图
我们将使用 WebSphere® Studio 5.0 的 Application Developer 配置和一个称为 Hibernator 的插件来开发应用程序,Hibernator 能简化一些配置 Hibernate 的工作。
设置 WebSphere Studio 和 Java 项目
首先,让我们花些时间准备实验所需的要素:
在 WebSphere Studio 中创建一个新的 Java 项目。 从 httpsourceforge.netprojectshibernate 下载 Hibernate。在撰写本文时,Hibernate 的版本是 1.2.4。 解压缩从 SourceForge 得到的 Hibernate 压缩文档,将其中的内容解压缩到一个临时目录。 将名为 hibernate.jar 的 JAR 文件导入到项目的基本目录。 从 Hibernate 分发包中的 lib 目录导入以下 jar 文件: commons-lang.jar commons-collections.jar commons-logging.jar xml-apis.jar xerces.jar 将 hibernate.jar 添加到您的 Java 构建路径(Java Build Path)(用鼠标右键单击 project - Properties - Java Build Path - Libraries - Add JARs...,然后指向您所导入的 hibernate.jar)。 从 SourceForge(httpsourceforge.netprojectshibernator)下载 Hibernate Eclipse 插件。您会看到,这个插件使得同步现有的 Java 类和定义我们的 O-R 映射规则的 Hibernate 映射文件更容易。在撰写本文时,该插件的版本是 0.9.3。 将这个插件的压缩文件解压缩到 [WSAD 5 InstallDir]eclipseplugins 目录。 要与 DB2 UDB 进行交互,我们还需要导入 DB2 JDBC 数据库驱动程序。导入缺省情况下位于 Cprogram filesIBMSQLLIBjava 目录的 db2java.zip 文件。确保将 db2java.zip 添加到类路径中。 我们已经在本文所附带的代码中包含了一些 JUnit 测试。如果要运行这些测试,需要导入缺省情况下位于 [WSAD5InstallDir]eclipsepluginsorg.junit_3.7.0 目录的 junit.jar 文件。 我们必须重新启动 WebSphere Studio,以便它注册我们所添加的插件。 配置 hibernate.properties
为了促进与 DB2 UDB 的通信,我们需要让 Hibernate 知道一些我们的数据库属性。为此,我们将创建一个名为 hibernate.properties 的文件,这个文件必须出现在我们应用程序的类路径中。在我们的示例中,我们将把这个属性文件放到项目的基本目录中,这个目录包含在类路径中。您可能需要针对您自己的数据库设置更改下列属性值。
hibernate.connection.driver_class = COM.ibm.db2.jdbc.app.DB2Driver hibernate.connection.url = jdbcdb2empl hibernate.connection.username = db2admin hibernate.connection.password = db2admin hibernate.dialect = cirrus.hibernate.sql.DB2Dialect
如果您曾经不得已编写过检索 JDBC 连接的代码,那么前四个参数对您来说应该是很熟悉的。hibernate.dialect 属性告诉 hibetnate 我们在使用 DB2“方言”(dialect)。设置这个“方言”允许 Hibernate 在缺省情况下启用一些特定于 DB2 的功能,这样您就不用手工设置它们了。
创建数据库模式
上面的属性文件引用了我们还未创建的名为 empl 的数据库。让我们继续向前,完成这项工作。让我们转到 DB2 命令行处理器:
db2= create db empl
db2= connect to empl user db2admin using db2admin
此外,我们需要用到一些表:
db2= create table Employee ( EID int NOT NULL PRIMARY KEY, FirstName varchar(30) NOT NULL, LastName varchar(30) NOT NULL, Email varchar(30) NOT NULL, ManagerEID int, DepartmentID int NOT NULL)
db2= create table Department( DepartmentID int NOT NULL PRIMARY KEY, Name varchar(30) NOT NULL, City varchar(30) NOT NULL, State varchar(30) NOT NULL)
创建要被映射的 JavaBeans
回想一下,您阅读本文目的正是要将 Java 对象映射到数据库。那我们就来定义这些对象:
创建新的类 Department: package com.ibm.hibernate_article;
public class Department { private int departmentID; private String name; private String city; private String state;}
创建新的类 Employee: package com.ibm.hibernate_article;
public class Employee {
private int employeeId; private String firstName; private String lastName; private String email; private Employee manager; private Department department;}
对于我们新创建的两个类:
在大纲视图中,用鼠标右键单击类名。 选择 Generate Getter and Setter...。 选择 All。 单击 OK。 请记住,所有的 setter 和 getter 都必须存在,不过它们的可视性无关紧要。这样,如果您需要维护不变的对象,那么您可以在构造该对象期间设置其状态,并且将所有 setter 方法设为私有。除了所创建的任何其它构造器之外,您还必须提供一个缺省构造器;不过,缺省构造器的可视性也可以设为私有。setter 和 getter 方法以及缺省构造器之所以必须存在,是因为 Hibernate 遵循 JavaBeans 语法并且使用这些方法特征符来在 OR 映射期间持久保持数据。
创建 XML 映射
既然 Java 类和数据库表已经准备就绪,现在我们需要定义 OR 映射。Hibernate 通过读取包含映射定义的 XML 文件来实现这个目标。
让我们首先为 Employee 类创建映射。
在编辑器中打开 Employee.java 文件。 单击 Window - Show View - Other - Hibernator - Hibernator(请参阅图 2)。 图 2. 显示 Hibernator 视图
在 Hibernator 视图中用鼠标右键单击,然后单击 Save(图 3)。 图 3. 用 Hibernator 插件生成 OR 映射 XML 文件
我们还必须做一些编辑工作,但该视图实际上没有提供编辑功能,它只是生成 .hbm.xml 文件。这样,我们将需要在常规的文件编辑器中打开 Employee.hbm.xml 文件。
分析映射文件 该插件生成了一个文件,内容如下:
xml version=1.0 !DOCTYPE hibernate-mapping PUBLIC -HibernateHibernate Mapping DTDEN httphibernate.sourceforge.nethibernate-mapping.dtd hibernate-mapping class name=com.ibm.hibernate_article.Employee table=employee many-to-one name=department property name=email property name=employeeId property name=firstName property name=lastName many-to-one name=manager class hibernate-mapping !-- parsed in 0ms --
您会注意到,在 DOCTYPE 中定义的文档类型定义(document type definition,DTD)文件存在于指定的 URL(即 httphibernate.sourceforge.nethibernate-mapping.dtd)。如果该映射文件存在于类路径中,那么 Hibernate 将总是首先从那里引用它。因为该映射文件在 hibernate.jar 文件中,所以将会在您的类路径中,因此,您将不必担心需要手工将它导入。这个文件用来定义 XML 文件中允许的有效标记。
hibernate-mapping 标记是这个 XML 文件中的基本标记。这个标记有两个可选的属性,但我们的应用程序不需要它们。请参阅 Hibernate 文档,了解关于这些特征的更多信息。
class 元素代表一个持久的 Java 类。它有一个 name(名称)属性,这个属性引用我们正在映射的 Java 类的全限定(用点隔开)类名。它还有一个 table(表)属性,这个属性引用我们的类所映射到的数据库表(即员工表)。该插件没有为我们生成 table 属性,所以我们将在下一节中添加它。
class 元素还必须包含一个 id 元素,用来指定哪个字段是该数据库表的主键,并指定如何生成该主键。我们同样将在下一节中讨论这个问题。
Hibernate 文档提到:“property 元素声明了持久的类的 JavaBean 样式属性”。该属性主要用于基本类型或字符串类型的实例变量。在我们的示例中,员工的名字必须用一个 property 元素来代表。
many-to-one(多对一)元素用于“与另一个持久类的普通关联……。关系模型是一种多对一(many-to-one)关联。(它实际上就是一个对象引用。)”在我们的示例中,Employee 类与 Department 类之间存在 many-to-one 关联。
修改映射文件 我们的 employeeId 实例变量将映射到数据库中的 EID 列。因为 EID 将成为我们的主键,所以我们需要除去为 employeeId 生成的 property 元素,并且用 id 元素替代它:
id name= employeeId column=EID generator class=assigned id
id 元素的 name 属性引用我们的类中的 JavaBean 参数的名称。column 属性引用数据库中我们映射到的列。generator 元素的 class 属性被设置成“assigned”,意思是我们打算自己指定对象中主键的值。对于自动生成主键,还有其它一些 Hibernate 选项可供选择。您可以在 Hibernate 文档中找到关于这些选项的更多信息。
现在,我们需要进一步修改该插件所生成的代码,并着手定义每一个 property 和 many-to-one 标记将映射到哪些列:
property name=email column=Email property name=firstName column=FirstName property name=lastName column=LastName
many-to-one name=department column=departmentID many-to-one name=manager column=managerEID
这样,修改后的文档内容如下:
xml version=1.0 !DOCTYPE hibernate-mapping PUBLIC -HibernateHibernate Mapping DTDEN httphibernate.sourceforge.nethibernate-mapping.dtd hibernate-mapping class name=com.ibm.hibernate_article.Employee table=employee id name=employeeId column=EID generator class=assigned id property name=email column=Email property name=firstName column=FirstName property name=lastName column=LastName many-to-one name=department column=departmentID many-to-one name=manager column=managerEID class hibernate-mapping
我们将对 Department.hbm.xml 做本质上一样的处理。最后得到的结果如下:
xml version=1.0 !DOCTYPE hibernate-mapping PUBLIC -HibernateHibernate Mapping DTDEN httphibernate.sourceforge.nethibernate-mapping.dtd hibernate-mapping class name=com.ibm.hibernate_article.Department table=department id name=departmentID column=DepartmentID generator class=assigned id property name=city column=City property name=name column=Name property name=state column=State class hibernate-mapping
创建数据源和会话
我们需要将 XML 映射装入到某种对象表示中,这样 Hibernate 才可以使用它们。具体做法是创建 cirrus.hibernate.Datastore 类的一个实例。然后我们告诉这个 Datastore 实例为给定的类存储映射信息,办法是调用 storeClass 方法并给这个方法提供给定类的 Class 对象。storeClass 方法知道使用全限定类名在同一个包内查找相应的 .hbm.xml 映射文件。
在拥有 Datastore 对象之后,我们需要用它来构建 SessionFactory。这个 SessionFactory 将负责创建一些 Session 对象。Hibernate 文档将会话定义为“单线程的、存在时间短的对象,代表应用程序与持久存储之间的对话”。会话包装 JDBC 连接,充当 Transaction 对象的工厂,并管理应用程序中的持久对象。会话可以跨越多个事务,所以它不必像事务那样代表一个工作原子单元。
让我们创建一个静态的初始化程序,它将负责创建 SessionFactory 对象。当第一次引用该类时,这个静态的初始化程序将装入一次。在静态地装入这个初始化程序之后,我们将不再需要重新装入 Employee 和 Department 类映射。
private SessionFactory sessionFactory;
static { try { Datastore ds = Hibernate.createDatastore(); ds.storeClass(Employee.class);
[1] [2] 下一页 没有相关教程
|