Java
  Home arrow Java arrow Page 3 - Introduction to Mapping Redux
Dev Articles Forums 
ADO.NET  
Apache  
ASP  
ASP.NET  
C#  
C++  
ColdFusion  
COM/COM+  
Delphi-Kylix  
Design Usability  
Development Cycles  
DHTML  
Embedded Tools  
Flash  
Graphic Design  
HTML  
IIS  
Interviews  
Java  
JavaScript  
MySQL  
Oracle  
Photoshop  
PHP  
Reviews  
Ruby-on-Rails  
SQL  
SQL Server  
Style Sheets  
VB.Net  
Visual Basic  
Web Authoring  
Web Services  
Web Standards  
XML  
Mobile Linux 
App Generation ROI 
IBM® developerWorks 
Sun Developer Network 
Weekly Newsletter
 
Developer Updates  
Free Website Content 
 RSS  Articles
 RSS  Forums
 RSS  All Feeds
Write For Us Get Paid 
Request Media Kit
Contact Us 
Site Map 
Privacy Policy 
Support 
 USERNAME
 
 PASSWORD
 
 
  >>> SIGN UP!  
  Lost Password? 
JAVA

Introduction to Mapping Redux
By: O'Reilly Media
  • Search For More Articles!
  • Disclaimer
  • Author Terms
  • Rating: 5 stars5 stars5 stars5 stars5 stars / 1
    2007-05-03

    Table of Contents:
  • Introduction to Mapping Redux
  • Writing a Mapping Document
  • Generating Some Class
  • Cooking up a Schema
  • Connecting Hibernate to MySQL

  • Rate this Article: Poor Best 
      ADD THIS ARTICLE TO:
      Del.ici.ous Digg
      Blink Simpy
      Google Spurl
      Y! MyWeb Furl
    Email Me Similar Content When Posted
    Add Developer Shed Article Feed To Your Site
    Email Article To Friend
    Print Version Of Article
    PDF Version Of Article
     
     
    ADVERTISEMENT


    Introduction to Mapping Redux - Generating Some Class


    (Page 3 of 5 )

    Our mapping contains information about both the database and the Java class between which it maps. We can use it to help us create both. Let’s look at the class first.

    How do I do that?

    The Hibernate Extensions you installed in Chapter 1 included a tool that can write Java source matching the specifications in a mapping document, and an Ant task that makes it easy to invoke from within an Ant build file. Edit build.xml to add the portions shown in bold in
    Example 2-2.

    Example 2-2. The Ant build file updated for code generation

     1 <project name="Harnessing Hibernate: The Developer's Notebook"
     2          default="db" basedir=".">
     3  <!-- Set up properties containing important project directories -->
     4  <property name="source.root" value="src"/>
     5  <property name="class.root" value="classes"/>
     6  <property name="lib.dir" value="lib"/>
     7  <property name="data.dir" value="data"/>
     8
     9  <!-- Set up the class path for compilation and execution -->
    10  <path id="project.class.path">
    11     <!-- Include our own classes, of course -->
    12     <pathelement location="${class.root}" />
    13     <!-- Include jars in the project library directory -->
    14     <fileset dir="${lib.dir}">
    15       <include name="*.jar"/>
    16     </fileset>
    17   </path>
    18
    19   <target name="db" description="Runs HSQLDB database management UI
    20 against the database file--use when application is not running">
    21     <java classname="org.hsqldb.util.DatabaseManager"
    22            fork="yes">
    23       <classpath refid="project.class.path"/>
    24       <arg value="-driver"/>
    25       <arg value="org.hsqldb.jdbcDriver"/>
    26       <arg value="-url"/>
    27       <arg value="jdbc:hsqldb:${data.dir}/music"/>
    28       <arg value="-user"/>
    29       <arg value="sa"/>
    30     </java>
    31  </target>
    32
    33  <!-- Teach Ant how to use Hibernate's code generation tool -->
    34  <taskdef name="hbm2java"
    35            classname="net.sf. hibernate.tool.hbm2java.Hbm2JavaTask"
    36           classpathref="project. class.path"/>
    37
    38  <!-- Generate the java code for all mapping files in our source tree -->
    39  <target name="codegen"
    40          description="Generate Java source from the O/R mapping files">
    41   <hbm2java output="${source.root}">
    42     <fileset dir="${source.root}">

    43         <include name="**/*.hbm.xml"/>
    44       </fileset>
    45     </hbm2java>
    46   </target>
    47
    48  </project>

    We added a taskdef (task definition) and a new target to the build file. The task definition at line 33 teaches Ant a new trick: it tells Ant how to use the hbm2java tool that is part of the Hibernate Extensions, with the help of a class provided for this purpose. Note that it also specifies the class path to be used when invoking this tool, using the project.class.path definition found earlier in the file.

    The codegen target at line 38 uses the new hbm2java task to run Hibernate’s code generator on any mapping documents found in the src tree, writing the corresponding Java source. The pattern **/*.hbm.xml” means “any file ending in .hbm.xml, within the specified directory, or any subdirectory, however deeply  nested.”

    Let’s try it! From within your top-level project directory (the folder containing build.xml), type the following command:

      ant codegen

    You should see output like this:

      Buildfile: build.xml

      codegen:
       [hbm2java] Processing 1 files.
       [hbm2java] Building hibernate objects
       [hbm2java] log4j:WARN No appenders could be found for logger (net.sf.
      hibernate.util.DTDEntityResolver).
       [hbm2java] log4j:WARN Please initialize the log4j system properly.

    The warnings are griping about the fact that we haven’t taken the trouble to set up the logging environment that Hibernate expects. We’ll see how to do that in the next example. For now, if you look in the directory src/com/oreilly/hh, you’ll see that a new file namedTrack.java hasappeared, with the content shown in Example 2-3.

    Example 2-3. Code generated from the Track mapping document

      1 package com.oreilly.hh;
      2
      3 import java.io.Serializable;
      4 import java.util.Date;
      5 import org.apache.commons.lang.builder.EqualsBuilder;
      6 import org.apache.commons.lang.builder.HashCodeBuilder;
      7 import org.apache.commons.lang.builder.ToStringBuilder;
      8
      9 /**
     10  *     Represents a single playable track in the music database.
     11  *     @author Jim Elliott (with help from Hibernate)
     12  *
     13 */
     14 public class Track implements Serializable {
     15
     16    /** identifier field */
     17    private Integer id;
     18
     19    /** persistent field */
     20    private String title;
     21
     22    /** persistent field */
     23    private String filePath;
     24
     25    /** nullable persistent field */
     26    private Date playTime;
     27
     28    /** nullable persistent field */
     29    private Date added;
     30
     31    /** nullable persistent field */
     32    private short volume;
     33
     34    /** full constructor */
     35    public Track(String title, String filePath, Date playTime,
                    Date added, short volume) {
     36       this.title = title;
     37       this.filePath = filePath;
     38       this.playTime = playTime;
     39       this.added = added;
     40       this.volume = volume;
     41    }
     42
     43    /** default constructor */
     44    public Track() {
     45    }
     46
     47    /** minimal constructor */
     48    public Track(String title, String filePath) {
     49       this.title = title;
     50       this.filePath = filePath;
     51    }
     52
     53    public Integer getId() {
     54       return this.id;
     55    }
     56
     57    protected void setId(Integer id) {
     58       this.id = id;
     59    }
     60
     61    public String getTitle() {
     62       return this.title;
     63    }
     64
     65    public void setTitle(String title) {
     66       this.title = title;
     67    }
     68
     69    public String getFilePath() {
     70       return this.filePath;
     71    }
     72
     73    public void setFilePath(String filePath) {
     74       this.filePath = filePath;
     75    }
     76
     77    /**
     78     * Playing time
     79     */
     80    public Date getPlayTime() {
     81       return this.playTime;
     82    }
     83
     84    public void setPlayTime(Date playTime) {
     85       this.playTime = playTime;
     86    }
     87
     88    /**
     89     * When the track was created
     90     */
     91    public Date getAdded() {
     92       return this.added;
     93    }
     94
     95    public void setAdded(Date added) {
     96       this.added = added;
     97    }
     98
     99    /**
    100     * How loud to play the track
    101     */
    102    public short getVolume() {
    103       return this.volume;
    104    }
    105
    106    public void setVolume(short volume) {
    107       this.volume = volume;
    108    }
    109
    110    public String toString() {
    111       return new ToStringBuilder(this)
    112           .append("id", getId())
    113           .toString();
    114    }
    115
    116    public boolean equals(Object other) {
    117       if ( !(other instanceof Track) ) return false;
    118       Track castOther = (Track) other;
    119       return new EqualsBuilder()
    120          .append(this.getId(), castOther.getId())
    121          .isEquals();
    122    }
    123
    124    public int hashCode() {
    125       return new HashCodeBuilder()
    126          .append(getId())
    127          .toHashCode();
    128    }
    129
    130 }

    What just happened?

    Ant found all files in our source tree ending in .hbm.xml (just one, so far) and fed it to the Hibernate code generator, which analyzed it, and wrote a Java class meeting the specifications we provided for the Track mapping.

    That can save a lot of time and fairly repetitive activity. I could get used to it.

    You may find it worthwhile to compare the generated Java source with the mapping specification from which it arose (Example 2-1). The source starts out with the proper package declaration, which is easy for hbm2java to figure out from the fully qualified class name required in the mapping file. There are a couple of imports to make the source more readable. The three potentially unfamiliar entries (lines 5–7) are utilities from the Jakarta Commons project that help in the creation of correctly implemented and useful toString(), equals(), and hashCode() methods.

    The class-level JavaDoc at line 10 should look familiar, since it comes right from the “class-description” meta tag in our mapping document. The field declarations are derived from the id (line 17) and property (lines 20–32) tags defined in the mapping. The Java types used are derived from the property types in the mapping document. We’ll delve into the full set of value types supported by Hibernate later on. For now, the relationship between the types in the mapping document and the Java types used in the generated code should be fairly clear.

    One curious detail is that an Integer wrapper has been used for id, while volume is declared as a simple, unwrapped short. Why the difference? It relates to the fact that the ID/key property has many important roles to play in the O/R mapping process (which is why it gets a special XML tag in the mapping document, rather than being just another property). Although we left it out in our specification, one of the choices you need to make when setting up an ID is to pick a special value to indicate that a particular instance has not yet been saved into the database. Leaving out this unsaved-value attribute, as we did, tells Hibernate to use its default interpretation, which is that unsaved values are indicated by an ID of null. Since native int values can’t be null, they must be wrapped in a java.lang.Integer, and Hibernate took care of this for us.

    When it comes to the volume property, Hibernate has no special need or use for it, so it trusts us to know what we’re doing. If we want to be able to store null values for volume, perhaps to indicate “no change,” we need to explicitly use java.lang.Short rather than short in our mapping document. (Had we not been sneakily pointing out this difference, our example would be better off explicitly using java.lang.Integer in our ID mapping too, just for clarity.)

    I know, I’m a perfectionist. I only bother to pick nits because I think Hibernate is so useful!

    Another thing you might notice about these field declarations is that their JavaDoc is quite generic—you may be wondering what happened to the “field-description” meta tags we put in the mapping document for playTime, added and volume. It turns out they appear only later, in the JavaDoc for the getter methods. They are not used in the setters, the actual field declarations, nor as @param entries for the constructor. As an avid user of a code-completing Java editor, I count on pop-up JavaDoc as I fill in arguments to method calls, so I’m a little disappointed by this limitation. Of course, since this is an open source project, any of us can get involved and propose or undertake this simple fix. Indeed, you may find this already remedied by the time you read this book. Once robust field and parameter documentation is in place, I’d definitely advocate always providing a brief but accurate field-description entry for your properties.

    After the field declarations come a trio of constructors. The first (line 35) establishes values for all properties, the second (line 44) allows instantiation without any arguments (this is required if you want the class to be
    usable as a bean, such as on a Java Server Page, a very common use for data classes like this), and the last (line 48) fills in just the values we’ve indicated must not be null. Notice that none of the constructors set the value of id; this is the responsibility of Hibernate when we get the object out of the database, or insert it for the first time.

    Consistent with that, the setId() method on line 57 is protected, as requested in our id mapping. The rest of the getters and setters are not surprising; this is all pretty much boilerplate code (which we’ve all written too many times), which is why it’s so nice to be able to have the Hibernate extensions generate it for us.

    WARNING

    If you want to use Hibernate’s generated code as a starting point and then add some business logic or other features to the generated class, be aware that all your changes will be silently discarded the next time you run the code generator. In such a project you will want to be sure the hand-tweaked classes are not regenerated by any Ant build target.

     

    Even though we’re having Hibernate generate our data classes in this example, it’s important to point out that the getters and setters it creates are more than a nice touch. You need to put these in your persistent classes for any properties you want to persist, since Hibernate’s fundamental persistence architecture is based on reflective access to Java-Beans™-style properties. They don’t need to be public if you don’t want them to; Hibernate has ways of getting at even properties declared protected or private, but they do need accessor methods. Think of it as enforcing good object design; the Hibernate team wants to keep the implementation details of actual instance variables cleanly separated from the persistence mechanism.

    More Java Articles
    More By O'Reilly Media


       · This article is an excerpt from the book "Hibernate: A Developer's Notebook,"...
     

    Buy this book now. This article is excerpted from chapter two of Hibernate: A Developer's Notebook, written by James Elliott (O'Reilly; ISBN: 0596006969). Check it out today at your favorite bookstore. Buy this book now.

    JAVA ARTICLES

    - Deploying Multiple Java Applets as One
    - Deploying Java Applets
    - Understanding Deployment Frameworks
    - Database Programming in Java Using JDBC
    - Extension Interfaces and SAX
    - Entities, Handlers and SAX
    - Advanced SAX
    - Conversions and Java Print Streams
    - Formatters and Java Print Streams
    - Java Print Streams
    - Wildcards, Arrays, and Generics in Java
    - Wildcards and Generic Methods in Java
    - Finishing the Project: Java Web Development ...
    - Generics and Limitations in Java
    - Getting Started with Java Web Development in...






    © 2003-2008 by Developer Shed. All rights reserved. DS Cluster 4 hosted by Hostway
    Stay green...Green IT