More Books
Hibernate: A J2EE Developer's Guide
Hibernate: A J2EE™ Developer's Guide
Table of Contents
Copyright
Acknowledgments
About the Author
Preface
Required Skills
Roadmap
Chapter 1. Overview
Why Object/Relational Mapping?
What Is Hibernate?
Comparing JDBC to Hibernate
Hibernate's Mapping System
Other Java/Database Integration Solutions
How to Obtain and Install
Supported Databases
Chapter 2. Getting Oriented
Application Architecture
Mapping Files
Generating Java Source
Application Configuration
Web Application
JSP Interface
Chapter 3. Starting from Java
Java Object Model
Generated Mapping Files
Generated Schema
Working with Artifacts and Owners
Chapter 4. Starting from an Existing Schema
Initial Schema
Using Middlegen
Generated Mapping Files
Generated Java
Working with the Database
Chapter 5. Mapping Files
Basic Structure
Mapping File Reference
Chapter 6. Persistent Objects
Sessions
Objects and Identity
Life-Cycle Methods
Chapter 7. Relationships
Database Relationships
Java Collection Relationships
Java Class Relationships
Any-Based Relationships
Bi-directional Relationships
Chapter 8. Queries
HQL
HQL Reference
Select
From
Where
Group By
Having
Order By
Criteria Queries
Native SQL Queries
Chapter 9. Transactions
Introduction to Transactions
Optimistic and Pessimistic Locking
Chapter 10. Performance
Finding and Solving Problems
Queries
Inserts
Connection Pooling
Caching
Chapter 11. Schema Management
Updating an Existing Schema
Generating Update and Drop Scripts
Chapter 12. Best Practices, Style Guide, Tips and Tricks
Reducing Code with Inversion of Control
Reducing Session Creation Impact with ThreadLocal
Using Hibernate as an EJB BMP Solution
Integrating with Other Technologies
Applications That Use Hibernate
Strategies for Getting Started
Chapter 13. Future Directions
Hibernate 3.0
EJB 3.0
Here and Now
Index
SYMBOL
A
B
C
D
E
F
G
H
I
J
K
L
M
N
O
P
Q
R
S
T
U
V
W
X

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

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).

Figure 2.2. Generated Classes


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.