Using Middlegen
Assuming that the script has been used to generate the schema in the database, the next step is to set up and configure Middlegen. Middlegen is a tool for generating mapping files and other artifacts from an existing database schema. It can be used to generate bindings for a variety of other technologies (including EJB 2.X) in addition to Hibernate. That's what Middlegen doesgenerate developer artifacts (for the "middle tier") from a relational database.
Middlegen uses JDBC to connect to a database and then generate application resources and code from that database. Although this may seem counter-intuitive, Ant is used as the engine for launching and configuring Middlegen. The advantage of using Ant is that the graphical user interface and the command-line build process can share a single configuration.
Obtaining Middlegen
You can download the complete Middlegen release from SourceForge.net at http://sourceforge.net/projects/middlegen. Unfortunately, the default download includes a large suite of files unnecessary for use with Hibernate (for example, extensive support for EJB CMP 2.0 and JDO). A great many complex build files are included, as well as a large suite of libraries. To make it easier to understand, this chapter will use a somewhat stripped down version of the Middlegen 2.0 VO files, available for download at http://www.cascadetg.com/hibernate/.
Figure 4.1 shows the files contained in the archive. The lib directory contains the *.jar files needed by the project. The Commons, log4j, Middlegen, and Velocity JAR files are included with the Middlegen 2.0 VO project, and the MySQL driver is available for download from http://www.mysql.com/.

As you will have noticed, there are several other folders in the distribution. The prefs directory contains the preferences generated by the Middlegen GUI. The hbm directory contains the *.hbm.xml files generated by Middlegen. Similarly, the src directory contains Java source files generated from the *.hbm.xml files by an Ant task.
The build.xml file is an Ant script used to launch the Middlegen GUI (see Chapter 2 for more information on Ant). The schema.sql file contains the MySQL SQL statements, as shown in Listing 4.1. The various log files are generated during the run of the Ant script, and may be useful if you encounter problems.
Configuring Middlegen
The most important file in the distribution is the build.xml file. If you are accustomed to working with Ant, you may expect build.xml to serve primarily as a tool for performing automated builds. Middlegen, however, uses Ant and build.xml as a configuration tool for the graphical user interface and the automated build process. When you are first building your application, you will use the Middlegen user interface, but later you may wish to merely use Middlegen as an automated build tool.
|
If you are accustomed to simply double-clicking an application to launch it, the use of Ant to configure and launch Middlegen may feel strange. Those who favor this approach argue that it allows you to reuse a common configuration setting for both the graphic user interface and the command-line version. In practice, it probably would be better for Middlegen to operate as an ordinary application, saving and loading configuration as a standalone XML file, which could then be referenced by the build task. This would allow for a shorter build file and a more accessible first impression when using Middlegen.
Middlegen is open-source, so feel free to download it and start working. |
Listing 4.2 show the header for the build.xml file, containing the various configuration options for the build script. Of particular interest are the package settings (allowing you to control the package for the generated source) and the JDBC connectivity settings.
Listing 4.2. Ant Build and Run Script
<project default="all">
<!-- project name -->
<property name="name" value="chapter4" />
<!-- installation configuration -->
<property name="hibernate_path"
value="C:\devenv\hibernate-2.1.2"/>
<property name="hibernate_tool_path"
value="C:\devenv\hibernate-extensions-2.0.2\tools"/>
<property name="project.dir"
value=
"C:\devenv\eclipsev3_M4\workspace\hibernate\com\cascadetg\ch04" />
<!-- the generated package info -->
<property name="package" value="com.cascadetg.ch04" />
<property name="package.dir" value="\com\cascadetg\ch04" />
<!-- various sub directories -->
<property name="lib.dir" value=".\lib" />
<property name="prefs.dir" value=".\prefs" />
<property name="build.hbm.dir" value=".\hbm" />
<property name="build.src.dir" value=".\src" />
<!-- name of the database script -->
<property name="database.script.file" value="schema.sql" />
<!-- JDBC connectivity information -->
<property name="database.driver.file"
value="${lib.dir}\mysql-connector-java-3.0.10-stable-bin.jar"/>
<property name="database.driver.classpath"
value="${database.driver.file}"/>
<property name="database.driver"
value="com.mysql.jdbc.Driver"/>
<property name="database.url"
value="jdbc:mysql://localhost/hibernate"/>
<property name="database.userid" value="root"/>
<property name="database.password" value=""/>
<property name="database.schema" value=""/>
<property name="database.catalog" value=""/>
As shown in Listing 4.3, the default all target will build the tables in the database by executing a script containing the commands, as shown in Listing 4.1, then invoke Middlegen (generating the *.hbm.xml files), create the Java sources from the *.hbm.xml files, and finally copy the files into the project development tree.
Listing 4.3. Building Tables
<!-- default target -->
<target name="all"
depends="build_tables,middlegen,build_hbm,copy_files" />
<!-- calls and executes the schema script -->
<target name="build_tables">
<sql
classpath="${database.driver.classpath}"
driver="${database.driver}"
url="${database.url}"
userid="${database.userid}"
password="${database.password}"
print="true"
output="build_tables_result.log">
<transaction src="${database.script.file}" />
</sql>
</target>
Listing 4.4 shows the target to launch and configure Middlegen. First, a Middlegen Ant task definition is specified, and then the Middlegen task is configured.
A single output plugin is used to indicate that the application uses Hibernate (Middlegen can also create EJB or JDO mappings, using other plugins).
Note that the four tables described by the schema are explicitly named in the file. Middlegen will load these tables and attempt to deduce the relationships between them from the JDBC driver metadata. If the relationship is sufficiently complex, it can specify additional configuration data.
|
You can use additional tags to describe many-to-many relationships (as described in Chapter 7) or relationships that are not described by foreign-key constraints (useful if your database doesn't support foreign keys).
For more information on these options, see http://boss.bekk.no/boss/middlegen/ant/index.html. For example, to use a many-to-many association table without an independent generated class, you can use the many2many configuration tag. Alternatively, you might use crossref sub-elements of the table tag to declare foreign-key relationships. There are multiple ways to model most relationships, many of which may be equally useful. |
Listing 4.4. Middlegen Task
<!-- Target to run Middlegen -->
<target name="middlegen"
description="Run Middlegen"
unless="middlegen.skip">
<mkdir dir="${prefs.dir}"/>
<echo message="Class path = ${basedir}"/>
<taskdef name="middlegen"
classname="middlegen.MiddlegenTask">
<classpath>
<fileset dir="${lib.dir}">
<include name="*.jar"/>
<include name="*.properties"/>
</fileset>
</classpath>
</taskdef>
<!-- Note the gui=true value. Set this to false to use in
a command-line fashion -->
<middlegen
appname="${name}"
prefsdir="${prefs.dir}"
gui="true"
databaseurl="${database.url}"
driver="${database.driver}"
username="${database.userid}"
password="${database.password}"
chema="${database.schema}"
catalog="${database.catalog}"
>
<!-- The hibernate plugin-->
<hibernate
destination="${build.hbm.dir}"
package="${package}"
javaTypeMapper=
"middlegen.plugins.hibernate.HibernateJavaTypeMapper"
/>
<table name="student" />
<table name="course" />
<table name="exam" />
<table name="examresult" />
<!-- You can declare additional tables and
relationships here. You can use this to
override or add to the JDBC derived information
-->
<!-- For example...
<many2many>
<tablea name="student"/>
<jointable name="examresult" generate="false"/>
<tableb name="class"/>
</many2many>
-->
</middlegen>
</target>
Listing 4.5 shows the target that generates the Java sources from the *.hbm.xml files (similar to the files shown in Chapter 2) after Middlegen exits from the GUI.
Listing 4.5. Building Java Source Files
<!-- creates the Java sources from the HBM files.
<target name="build_hbm" description="builds the Java sources">
<mkdir dir="${build.src.dir}"/>
<echo message="src dir = ${build.src.dir}"/>
<echo message="target hbm
files = ${build.hbm.dir}${package.dir}\" />
<taskdef name="hbm2java"
classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask">
<classpath>
<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"/>
</classpath>
</taskdef>
<hbm2java config="hbm2java_config.xml"
output="${build.src.dir}">
<fileset
dir="${build.hbm.dir}${package.dir}" includes="*.hbm.xml"/>
</hbm2java>
</target>
Finally, as shown in Listing 4.6 the project provides a task to copy the resulting source and mapping files from the generated projects into the development tree.
Listing 4.6. Building Java Source Files
<!-- copies the results to your project source tree.
Note that you need both the Java source and the
HBM files. -->
<target name="copy_files" description="copies results to project">
<copy todir="${project.dir}">
<fileset dir="hbm\${package.dir}" />
<fileset dir="${build.src.dir}\${package.dir}" />
<fileset file="${database.script.file}" />
</copy>
</target>
</project>
Finally, as shown in Listing 4.6, the project provides a task to copy the resulting source and mapping files from the generated projects into the development tree.
Running Middlegen
Before running Middlegen as shown, you must have first successfully installed MySQL, created a database named hibernate, and installed Ant. Once you have done all this, simple open a terminal, change to the directory containing the build file, type ant, and press return.
The terminal will begin by generating output, as shown in Listing 4.7, and then will launch the Middlegen graphical interface.
Listing 4.7. Initial Middlegen Output
C:\devenv\cascadetg-middlegen-2.0-vo>ant
Buildfile: build.xml
build_tables:
[sql] Executing file: C:\devenv\cascadetg-middlegen-2.0-vo\schema.sql
[sql] 33 of 33 SQL statements executed successfully
middlegen:
[echo] Class path = C:\devenv\cascadetg-middlegen-2.0-vo
[middlegen] log4j:WARN No appenders could be found for logger (middlegen.Middlegen).
[middlegen] log4j:WARN Please initialize the log4j system properly.
[middlegen] Database URL:jdbc:mysql://localhost/hibernate
[middlegen]
********************************************************
[middlegen] * CTRL-Click relations to modify their cardinality *
[middlegen] * SHIFT-Click relations to modify their directionality *
[middlegen] ********************************************************
<GUI launches>
Figure 4.2 shows the Middlegen user interface in action. The boxes can be organized to fit aesthetic requirements. Clicking on a table will let you set table-specific configuration options; clicking on a column name will allow you to set column-specific configuration options.
By interacting with the Middlegen interface, you configure the *.hbm.xml files that will be generated by Middlegen. While the interface allows you to modify the cardinality and direction of the bindings, you can't create or delete associationsthis must be done in the database via foreign keys or via the Middlegen build.xml file.
The following modifications were made in the Middlegen interface for this application.
The key generator for all four tables is changed from assigned to native. For more information on these options, see the generator tag in Chapter 5. Change the score Java type from java.lang.Long to int.
After these changes are made, the Generate button should be clicked to actually generate the *.hbm.xml files. The close box is used to exit. After Middlegen exits, the Ant build script will continue, as shown in Listing 4.8.
Listing 4.8. Concluding Middlegen Output
<GUI terminates>
[middlegen] Updated preferences in C:\devenv\cascadetg-middlegen-2.0-vo\prefs
\chapter4-prefs.pr
build_hbm:
copy_files:
[copy] Copying 4 files to C:\devenv\eclipsev3_M4\workspace\hibernate\com\cascadetg\ch04
all:
BUILD SUCCESSFUL
Total time: 11 minutes 38 seconds
C:\devenv\cascadetg-middlegen-2.0-vo>
|