In Hibernate Roundtrip Development, a scenario is presented to generate (Hibernate) POJO objects from a (legacy) database, also known as a bottom-up approach:
We applied this strategy to a MSSQL server database with a jTDS JDBC driver. We discuss the steps involved, analyse the results produced, and stipulate a pending issue.
The following refs were very helpful:
- Middlegen for Hibernate page
- Middlegen-Hibernate example and references therein
Our build.xml is based on the sample airline application that comes with the Middlegen distribution. The MSSQL specific settings include:
<property file="${basedir}/build.properties"/> <property name="lib.dir" value="${basedir}/lib"/> <property name="database.driver.file" value="${lib.dir}/jtds-0.9-rc1.jar"/> <property name="database.driver.classpath" value="${database.driver.file}"/> <property name="database.driver" value="net.sourceforge.jtds.jdbc.Driver" /> <property name="database.url" value="jdbc:jtds:sqlserver://amis_machine_name" /> <property name="database.userid" value="amis_username"/> <property name="database.password" value="amis_passwd"/> <property name="database.schema" value="dbo"/> <property name="database.catalog" value="RemoteUren"/>
The middlegen target itself is largely left unaltered:
<target name="middlegen" description="Run Middlegen" unless="middlegen.skip" depends="init,fail-if-no-xdoclet-1.2" > <mkdir dir="${build.gen-src.dir}"/> <taskdef name="middlegen" classname="middlegen.MiddlegenTask" classpathref="lib.class.path" /> <middlegen appname="${name}" prefsdir="${src.dir}" gui="${gui}" databaseurl="${database.url}" initialContextFactory="${java.naming.factory.initial}" providerURL="${java.naming.provider.url}" datasourceJNDIName="${datasource.jndi.name}" driver="${database.driver}" username="${database.userid}" password="${database.password}" schema="${database.schema}" catalog="${database.catalog}" > <html destination="${build.html.dir}"> /> <hibernate destination="${build.gen-src.dir}" package="${name}.hibernate" genXDocletTags="true" /> </middlegen> <mkdir dir="${build.classes.dir}"/> </target>
According to the above picture, we can even go one step further using the hbm2java tool. To this extent, we defined an additional task in the build.xml:
<target name="hbm2java" depends="middlegen" description="Generate .java from .hbm files."> <taskdef name="hbm2java" classname="net.sf.hibernate.tool.hbm2java.Hbm2JavaTask" classpathref="lib.class.path" /> <hbm2java output="${build.gen-src.dir}"> <fileset dir="${build.gen-src.dir}"> <include name="**/*.hbm.xml"/> </fileset> </hbm2java> </target>
After copying the jDTS jar to the lib dir (where all the middlegen-related jars reside), we could simply invoke middlegen by starting ant. We did not make use of the GUI, since there is no need for us to fine-tune the generated code (at least, not yet).
According to a Hibernate-knowledgeable collegue (Jasper Fontaine), applying Middlegen to the tables in the database resulted in clean and readable code in both the hbm2java-generated POJOs (plain old Java objects, containing private member variables representing the DB-columns with associated getters and setters) and the Hibernate mapping files. Both the POJOs and mapping files come close to what we would have been coding by hand.
However, a more general concern might be the fact that this way a layer of objects is procuded, which has a one-to-one relation with the tables in the RDBMS. This implies that a change in the tables will have consequences for the code that relies on those table-representing objects!
We have decided to keep working with Hibernate (and Middlegen), since its benefits (no need to write low-level data access code + transaction support) outweigh the disadvantages here.
Moreover, this drawback has largely been compensated in our case by employing the DAO (Data Access Object) pattern. In principle, this still leaves us the choice of JDBC, Hibernate, Toplink, or any other technology for the implementation of our DAO interfaces at a later stage (as a matter of fact, we used this approach before in a “study/trial application”, where we employed an abstract factory design pattern to be able to easily switch between these different “DAO providers”, see also this post).
One issue remains pending though. In the sample airline application that comes with the Middlegen distribution, it is possible to generate a Struts layer as well, departing fromt the tables in the database. As a first set-up, we would like to mimic this approach. However, the airline application is based on EJBs. Currently we did not succeed in constructing a similar build.xml file for our Hibernate-based solution, since the generated Struts Action Java classes are full of EJB-related references, despite the fact that our build.xml does not contain any EJB-related entries.
Very good article.
I am using Mddlegen with iSeries/AS400
http://rmwebcafe.blogspot.com/
By coincidence, I used Middlegen again yesterday evening! I found out that the JARs needed to run hbm2java (as mentioned in comment 5.) are available in the sample/lib directory of the Middlegen distribution. Just put them in your classpath and/or copy them over to your project directory.
It is already some time ago that I worked this out. However, I can quote from MJWall.com:
Indeed, I do remember that I needed to download several additional JARs.
hbm2java ? Which jar files includes this hbm2java task? I cant find it anywhere 🙁
The way I did it was from the Middlegen installation. First I made a copy of the included example, and adapted the build file to our situation. This way all necessary JAR files were available without problems.
this to be tested under hibernate installation or in middlegen installation? i.e. the build file should be frome which directory? I have problem configuring / running hibernate+middlegen please reply to my mail id.
Two follow-ups to this post are available:
Hibernate: dealing with lazy loading inevitable and
Struts, JAAS, Tomcat: getting acquainted