Saturday, March 10, 2012

Reverse engineering - Generating hbm.xml from annotated POJO

I have look for these particular scenario every where but couldnot found anything usefull other than the hibernate tools documentation. Reason the people not doing this is because hibernate - tools are mainly using for reverse engineering where this is not coming across. Only scenario i can think of where you need to generate a hibernate mapping xml from a POJO which is already annotated ( annotations are the successor of hibernate mapping xmls) is when you are in middle of the migration process from hibernate mapping xmls to annotations.

People already developing a product are not likely to suddenly adapting the changes. So they do it, step by step when it is needed so in such a case first you write annotation base POJOs but really not using them instead u generate the hbm.xml from the annotations, is the best way to work around. And also writing POJO separately and mapping separately increase the possibility of  erroneous of the code. Instead generating one automatically when the other given is much applicable which in case reduce   the time of the development and make the process more efficient.

enough talking now i will explain the process
only to generate the hbm mapping i only needed hibernate-tool-xx.jar and fremarker.jar but to run a complete hibernate base code using the generated hbm i need the following dependencies so before you start better to include all of them in to your lib directory

below jars are coming with hibernate distribution
antlr-2.7.6.jar
commons-logging-1.1.1.jar
dom4j-1.6.1.jar                                                              
hibernate3.jar
slf4j-api-1.6.1.jar
jta-1.1.jar
javassist-3.12.0.GA.jar

and you have to download these separately
commons-collections-3.2.1.jar
hibernate-jpa-2.0-api-1.0.1.Final.jar
jtidy-r8-21122004.jar
mysql-connector-java-5.0.4-bin.jar (if you use mysql as back end database)
slf4j-simple-1.6.1.jar
freemarker.jar
hibernate-tools-3.2.4.GA.jar

that is all you need. And lets begin coding you have to write an ant build script with following target and taskdef which need to create hbm.xml mapping for your pojo

 <taskdef name="hibernatetool"   
                classname="org.hibernate.tool.ant.HibernateToolTask"   
                classpathref="lib" />  
      <taskdef name="annotationconfiguration"   
                classname="org.hibernate.tool.ant.AnnotationConfigurationTask"   
                classpathref="lib" />  
      <target name="init" depends="copy-resources">  
           <hibernatetool destdir="${builddir}">  
                <classpath>  
                     <path location="${srcdir}" />  
                     <path location="${libdir}" />  
                     <path location="${builddir}" />  
                </classpath>  
                <annotationconfiguration configurationfile="${srcdir}/hibernate.cfg.xml" />  
                <hbm2hbmxml />  
           </hibernatetool>  
      </target>  

Put this ant file in to your project and write a POJO with annotations as they used to write in. (Everything is normal than the crazy work - trying to generate hbm.xml from annotations.)

And here is the important part. You have to include your pojo's full class path into your hibernate.cfg.xml (hibernate configuration file) as a mapping.

Below is my example hibernate.cfg.xml ,

 <?xml version='1.0' encoding='utf-8'?>  
 <!DOCTYPE hibernate-configuration PUBLIC  
 "-//Hibernate/Hibernate Configuration DTD//EN"  
 "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">  
 <hibernate-configuration>  
 <session-factory>  
  <property name="hibernate.connection.driver_class">  
 com.mysql.jdbc.Driver</property>  
  <property name="hibernate.connection.url">  
 jdbc:mysql://localhost:3306/testhib</property>  
  <property name="hibernate.connection.username">root</property>  
  <property name="hibernate.connection.password">1234</property>  
  <property name="hibernate.connection.pool_size">1</property>  
  <property name="show_sql">true</property>  
  <!-- <property name="hibernate.bytecode.provider">javassist</property> -->  
  <property name="dialect">org.hibernate.dialect.MySQLDialect</property>  
  <property name="hibernate.hbm2ddl.auto">update</property>  
  <!-- Mapping files -->  
  <mapping class="com.example.User"/>  
  <mapping class="com.example.Task"/>  
  </session-factory>  
 </hibernate-configuration>  

here my POJOs which are  "com.example.User"  and "com.example.Task"  list under the mapping where normally hbm.xml goes. What happen here is the when the ant target "init" is called it tell hibernate tool task to read the hibernate configuration file and find the mapping class files then it goes to class path folders defined under hibernatetool task, travel the folder structure defined in package name and find the .class file, read the annotations in the .class file and generate the mappings in your directory where you defined under "destdir".

1 comment:

  1. few other references to the topic have been listed below

    http://stackoverflow.com/questions/6871177/hbm2hbmxml-does-not-generate-hibernate-mapping/9649567#9649567

    http://docs.huihoo.com/hibernate/tools-reference-3.2.0/ant.html

    http://www.newgoodidea.com/static/n5721.jsf

    ReplyDelete