Generating Java Source
Given the *.hbm.xml files shown in Listing 2.1 and Listing 2.2, the next step is to generate the corresponding Java code. This is done with Ant. Listing 2.3 shows the complete Ant build.xml file used for this application.
|
Ant is a popular open-source build tool. It can be downloaded for free from http://ant.apache.org/. To use Ant, simply unzip or untar the distribution into a directory, place the /bin directory on your path, and make sure that your JAVA_HOME variable points to your Java 2 SDK installation.
If you are running on Windows and are not familiar with setting your path, you can invoke Ant directly. For example if Ant has been unzipped into the C:\devenv\ant\directory, you could call it by simply typing C:\devenv\ant\bin\ant.
Similarly, if you are running on Windows and your JAVA_HOME has not been set, you may find it easiest to simply add a line to the top of the \bin\ant.bat file setting JAVA_HOME.
set JAVA_HOME=C:\j2sdk1.4.1_03\
For Mac OS X and other UNIX systems, check the documentation for your preferred shell for more information on how to set your path and environment variables.
If you don't know how to set your path and environment variables, or don't want to deal with this, you can simply use an integrated development environment (IDE). Both Eclipse (http://www.eclipse.org/) and NetBeans (http://www.netbeans.org/) are free, open-source, multiplatform, and bundle an integrated version of Ant. |
Listing 2.3. Ant Build File
<?xml version="1.0"?>
<project name="ch03" default="all">
<target name="all" depends="build_hbm,deploy" />
<description>Hibernate starting with Java</description>
<!-- project name -->
<property name="name" value="chapter2" />
<!-- installation configuration -->
<!-- You'll need to set these depending on your library
installation directories -->
<property name="hibernate_path"
value="C:\devenv\hibernate-2.1.2"/>
<property name="hibernate_tool_path"
value="C:\devenv\hibernate-extensions-2.1\tools"/>
<!-- the generated package info -->
<property name="package" value="com.cascadetg.ch02" />
<property name="package.dir" value="\com\cascadetg\ch02" />
<property name="tomcat.app"
value="C:\Tomcat5\webapps\weblog\" />
<property name="tomcat.classes.dir"
value="C:\Tomcat5\webapps\weblog\WEB-INF\classes" />
<path id="project.class.path">
<pathelement
location="${hibernate_path}\hibernate2.jar"/>
<pathelement
location="${hibernate_tool_path}\hibernate-
tools.jar"/>
<pathelement location=
"${hibernate_path}\lib\commons-collections-2.1.jar"
/>
<pathelement location=
"${hibernate_path}\lib\commons-logging-1.0.3.jar"
/>
<pathelement location=
"${hibernate_path}\lib\commons-lang-1.0.1.jar" />
<pathelement location=
"${hibernate_path}\lib\xerces-2.4.0.jar" />
<pathelement location=
"${hibernate_tool_path}\lib\jdom.jar"/>
</path>
<!-- Normally, Ant build files are stored at the root of
the tree.
The builds for this book are on a per-chapter basis -->
<property name="base_dir" value="..\..\..\" />
<!-- creates the Java sources from the HBM files. -->
<target name="build_hbm" description="builds the Java
sources">
<taskdef name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java
.Hbm2JavaTask">
<classpath refid="project.class.path"/>
</taskdef>
<mkdir dir="${build.src.dir}"/>
<hbm2java config="hbm2java_config.xml"
output="${base_dir}">
<fileset dir="." includes="*.hbm.xml"/>
</hbm2java>
</target>
<!-- Builds and copies files into Tomcat WEB-INF classes -->
<target name="deploy" >
<echo message="compiling..." />
<javac srcdir="${base_dir}"
destdir="${tomcat.classes.dir}"
debug="on" includes="**/ch02/**">
<classpath refid="project.class.path"/>
</javac>
<echo message="copying..." />
<copy todir="${tomcat.classes.dir}${package.dir}">
<fileset dir="." casesensitive="yes">
<include name="**/*.hbm.xml"/>
</fileset>
</copy>
<copy todir="${tomcat.classes.dir}">
<fileset dir="${base_dir}" casesensitive="yes">
<include name="*.properties"/>
</fileset>
</copy>
</target>
<!-- Used to copy JSP files back into CVS managed folder. -->
<target name="copy_from_jsp">
<copy todir="${base_dir}\webapp">
<fileset dir="${tomcat.app}" casesensitive="yes" />
</copy>
</target>
</project>
Listing 2.3 contains several tasks. The task of principal interest is the build_hbm task, broken out into a separate listing in Listing 2.4. Note that this task relies on the net.sf.hibernate.tool.hbm2java.Hbm2JavaTask class, part of the Hibernate hbm2java tool suite. The actual function of the tool suite is straightforward; it reads the *.hbm.xml files and produces Java files according to rules specified in the hbm2java_config.xml file.
Listing 2.4. Building the Java Source
<!-- creates the Java sources from the HBM files. -->
<target name="build_hbm" description="builds the Java
sources">
<taskdef name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java
.Hbm2JavaTask">
<classpath refid="project.class.path"/>
</taskdef>
<mkdir dir="${build.src.dir}"/>
<hbm2java config="hbm2java_config.xml"
output="${base_dir}">
<fileset dir="." includes="*.hbm.xml"/>
</hbm2java>
</target>
The hbm2java_config.xml file is used to configure additional code-generation features. As shown in Listing 2.5, in addition to the standard Java code generation it will also generate a set of "finder" classes, utility functions that more easily retrieve objects by a specific property value.
Listing 2.5. Configuring hbm2java
<?xml version="1.0"?>
<codegen>
<generate renderer="net.sf.hibernate.tool.hbm2java
.BasicRenderer"/>
<generate
package="com.cascadetg.ch02.finder"
suffix="Finder"
renderer="net.sf.hibernate.tool.hbm2java
.FinderRenderer"/>
</codegen>
Running the Ant task will automatically generate (or regenerate) the Java classes as described in the mapping file.
Generated Persistent Classes
You may be surprised to find that the source generated by Hibernate is simply a set of ordinary JavaBeans (sometimes referred to as plain old Java objects or POJO). Figure 2.2 shows an overview of the generated source (the full argument constructors are omitted for readability).

For the sake of completeness, Listing 2.6 shows the code generated for the com.cascadetg.ch02.Author class. Probably the most shocking thing about the generated source is the lack of any especially unusual information. The class does implement java.io.Serializable, but there is no base class (although implements or extends can optionally be set by the mapping file). This makes Hibernate useful in a wide variety of situations, from an EJB 2.X BMP environment to a Swing client.
Listing 2.6. Author Persistent Object
package com.cascadetg.ch02;
import java.io.Serializable;
import java.util.Set;
import org.apache.commons.lang.builder.ToStringBuilder;
/** @author Hibernate CodeGenerator */
public class Author implements Serializable {
/** identifier field */
private String id;
/** nullable persistent field */
private String firstName;
/** nullable persistent field */
private String lastName;
/** nullable persistent field */
private String email;
/** persistent field */
private Set posts;
/** full constructor */
/*public Author(String firstName, String lastName,
String email, Set posts) {
this.firstName = firstName;
this.lastName = lastName;
this.email = email;
this.posts = posts;
}*/
/** default constructor */
public Author() {
}
/** minimal constructor */
public Author(Set posts) { this.posts = posts; }
public String getId() { return this.id; }
public void setId(String id) { this.id = id; }
public String getFirstName() { return this.firstName; }
public void setFirstName(String firstName) {
this.firstName = firstName; }
public String getLastName() { return this.lastName; }
public void setLastName(String lastName) {
this.lastName = lastName; }
public String getEmail() { return this.email; }
public void setEmail(String email) { this.email = email; }
public Set getPosts() { return this.posts; }
public void setPosts(Set posts) { this.posts = posts; }
public String toString() { return
new ToStringBuilder(this).append("id",
getId()).toString(); }
}
Now that the application has a set of Java classes corresponding to the database, it needs classes to actually perform work against the database.
 |