返回介绍

生成 Java 类

发布于 2025-04-21 21:42:11 字数 7829 浏览 0 评论 0 收藏

我们的映射文件中包含的是有关数据库、Java 类以及它们之间的映射关系的信息。可以用它来帮助我们创建数据库表和 Java 类。首先,我们来看看 Java 类。

应该怎么做

你在第 1 章安装的 Hibernate Tools 中包含一个工具,可以生成匹配映射文档规定的 Java 源代码。只要用一个 Ant 任务就能方便地在 Ant 的构建文件中调用这一工具。编辑 build.xml,把例 2-2 中的黑体部分添加进去。

例 2-2:Ant 构建文件(已经为生成 Java 代码而做了相应的更新)

<?xml version="1.0"?>

<project name="Harnessing Hibernate 3(Developer's Notebook Second Edition)"

default="db"basedir="."

xmlns:artifact="antlib:org.apache.maven.artifact.ant">

<!--Set up properties containing important project directories-->

<property name="source.root"value="src"/>

<property name="class.root"value="classes"/>

<property name="data.dir"value="data"/>

<artifact:dependencies pathId="dependency.class.path">

<dependency groupId="hsqldb"artifactId="hsqldb"version="1.8.0.7"/>

<dependency groupId="org.hibernate"artifactId="hibernate"

version="3.2.5.ga">

<exclusion groupId="javax.transaction"artifactId="jta"/>

</dependency>

<dependency groupId="org.hibernate"artifactId="hibernate-tools"

version="3.2.0.beta9a"/>

<dependency groupId="org.apache.geronimo.specs"

artifactId="geronimo-jta_1.1_spec"version="1.1"/>

<dependency groupId="log4j"artifactId="log4j"version="1.2.14"/>

</artifact:dependencies>

<!--Set up the class path for compilation and execution-->

<path id="project.class.path">

<!--Include our own classes, of course-->

<pathelement location="${class.root}"/>

<!--Add the dependencies classpath-->

<path refid="dependency.class.path"/>

</path>

<!--Teach Ant how to use the Hibernate Tools-->

<taskdef name="hibernatetool"❶

classname="org.hibernate.tool.ant.HibernateToolTask"

classpathref="project.class.path"/>

<target name="db"description="Runs HSQLDB database management UI

against the database file--use when application is not running">

<java classname="org.hsqldb.util.DatabaseManager"

fork="yes">

<classpath refid="project.class.path"/>

<arg value="-driver"/>

<arg value="org.hsqldb.jdbcDriver"/>

<arg value="-url"/>

<arg value="jdbc:hsqldb:${data.dir}/music"/>

<arg value="-user"/>

<arg value="sa"/>

</java>

</target>

<!--Generate the java code for all mapping files in our source tree-->

<target name="codegen"❷

description="Generate Java source from the O/R mapping files">

<hibernatetool destdir="${source.root}">

<configuration>

<fileset dir="${source.root}">

<include name="**/*.hbm.xml"/>

</fileset>

</configuration>

<hbm2java/>

</hibernatetool>

</target>

</project>

我们在构建文件中新添加了一个 taskedf(任务定义)元素,以及一个用于创建文件的 target 元素:

❶这一行的任务定义教给 Ant 一个新技巧:它告诉 Ant 如何使用 Hibernate Tools 中包含的 hibernate tool 任务(有个专门的类为该目的提供帮助)。注意,它也指定了调用这个工具时所需的类路径,并引用 project.calss.path 定义(这个定义包含了 Maven Ant Tasks 为我们管理的所有依赖文件)。当 Ant 需要使用 hibernate 工具时,通过这种办法,就可以找到它们。

❷codegen 构建目标使用 Hibernate Tools(hbm2java)模式来运行 Hibernate 的代码生成器,处理 src 源代码目录中找到的任何映射文件,生成相应的 Java 源代码。"**/*.hbm.xml"这样的匹配模式(pattern)是说“在指定目录或其任何子目录下(无论有多深),任何以.hbm.xml 结尾的文件”。

让我们先试一下吧!从你的项目目录的命令行中,输入以下命令:

ant codegen

你应该看到类似以下内容的输出(假设你运行过前面章节中 ant db 示例,运行那个例子会下载所有必需的依赖文件;如果你还没有运行过那个例子,则此时在下载这些依赖文件时,会多显示许多行信息):

Buildfile:build.xml

codegen:

[hibernatetool]Executing Hibernate Tool with a Standard Configuration

[hibernatetool]1.task:hbm2java(Generates a set of.java files)

[hibernatetool]log4j:WARN No appenders could be found for logger

(org.hibernate.cfg.Environment).

[hibernatetool]log4j:WARN Please initialize the log4j system properly.

BUILD SUCCESSFUL

Total time:2 seconds

以上提示信息大致说的是,我们在第 1 章配置构建文件要安装 log4j,但还没有建立它需要的配置文件,我们将在 2.3 节介绍解决这一问题的办法。现在,如果你去看看 src/com/orielly/hh/data 目录,就会发现出现了一个名为 Track.java 的新文件,其内容如例 2-3 所示。

例 2-3:根据 Track 映射文档生成的 Java 源代码

package com.oreilly.hh.data;

//Generated Sep 2,2007 10:27:53 PM by Hibernate Tools 3.2.0.b9

import java.util.Date;

/**

*Represents a single playable track in the music database.❶

*@author Jim Elliott(with help from Hibernate)

**/

public class Track implements java.io.Serializable{

private int id;

private String title;

private String filePath;

/**

*Playing time

*/

private Date playTime;

/**

*When the track was created

*/

private Date added;

/**

*How loud to play the track

*/

private short volume;

public Track(){

}

public Track(String title, String filePath, short volume){

this.title=title;

this.filePath=filePath;

this.volume=volume;

}

public Track(String title, String filePath, Date playTime, Date added,

short volume){

this.title=title;

this.filePath=filePath;

this.playTime=playTime;

this.added=added;

this.volume=volume;

}

public int getId(){

return this.id;

}

protected void setId(int id){❹

this.id=id;

}

public String getTitle(){

return this.title;

}

public void setTitle(String title){

this.title=title;

}

public String getFilePath(){

return this.filePath;

}

public void setFilePath(String filePath){

this.filePath=filePath;

}

/**

**Playing time

*/

public Date getPlayTime(){

return this.playTime;

}

public void setPlayTime(Date playTime){

this.playTime=playTime;

}

/**

**When the track was created

*/

public Date getAdded(){

return this.added;

}

public void setAdded(Date added){

this.added=added;

}

/**

**How loud to play the track

*/

public short getVolume(){

return this.volume;

}

public void setVolume(short volume){

this.volume=volume;

}

}

这个文件是怎么生成的?Ant 会找出源代码树中所有以.hbm.xml 结尾的文件(目前只有一个),把它们传给 Hibernate 的代码生成器,该代码生成器会分析映射文件,并生成一个满足 Track 映射文件中指定映射要求的 Java 类文件。很明显,这个工具可以为我们节省很多时间,并帮我们完成一些重复性的工作!

注意:Hibernate 可以为我们节省许多时间并完成很多繁琐的操作。要不然,我们一定会被它们搞得晕头转向。

比较生成的 Java 源代码和映射文件中的映射规定(例 2-1),你会有所收获。源代码以相应的包(package)声明作为开始,对于 hbm2java 而言,根据映射文件中指定的完全限定的类名,就可以容易地确定正确的包名:

❶类级的 JavaDoc 看起来应该很眼熟,因为它来自映射文档中 meta 标签的"class-description"。

❷字段声明是来自于映射文档中定义的 id 和 property 标签。源代码中所用到的 Java 类型都是源自于映射文档中的 property 类型声明。学习有关 Hibernate 支持的全部值类型,可以参阅附录 E 提到的资源。目前而言,映射文件内的类型和已生成的代码内的 Java 类型两者间的关系应该相当明确。

❸字段声明之后是三个构造函数的定义。第一个构造函数是创建实例时不用任何参数(如果想让你的类能够作为标准的 bean 来使用,例如在 JSP(Java Server Page)内使用,这是这种数据类非常常见的用法);第二个构造函数只需要提供映射文档中标明不得为 null 的值;最后一个构造函数是为所有属性赋值。注意,这些构造函数都没设置 id 属性的值,当我们从数据库把对象取出或者第一次将对象数据插入数据库时,Hibernate 负责帮我们做这件事。

❹同样,setId()方法的访问类型是 protected,与 id 的映射配置的要求是一样的。后面的 getter 和 setter 方法就没什么特别之处了,都是些照本宣科式的程序代码(我们都写过无数次了),这就是让 Hibernate 工具为我们生成这些代码的妙处所在。

如果你想使用 Hibernate 生成的代码作为起点,并在生成的 Java 类中添加某些业务逻辑或其他功能,一定要记住,你所做出的修改在下一次运行代码生成器时,都会被“悄悄”地丢弃。在这样的项目中,你需要确保手工修改过的类不会被任何 Ant 的构建目标任务重新生成。一种常用的技巧是,把需要手工修改的类扩展成 Hibernate 生成的类。这也是为什么我们要将映射生成的 Java 类隔离到它们自己的代码包和子目录中的原因之一。

虽然此例中 Hibernate 为我们生成了数据类,但需要指出的一个要点是,Hibernate 创建的 getter 和 setter 方法不仅仅是为了样子好看。对于你需要持久化的任何属性,在持久类中都必须具有 getter 和 setter 方法。这是因为 Hibernate 底层的持久化架构是通过反射机制来访问 JavaBeans 风格的属性的。如果你不希望类的属性是公共(public)的,它们可以不必是 public 的(即使属性被声明为 protected 或 private, Hibernate 还是有办法取得这些属性的值),但它们必须具有访问器和修改器方法,即 getter(访问器)和 setter(修改器)方法。这一点也是优秀的面向对象设计应该遵循的准则;Hibernate 团队希望把实际的实例变量(instance variable)的实现细节与底层持久化保存机制完全分离开来。

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。