Friday, August 30, 2013

Hibernate reverse engineering tool adjustments

Hibernate reverse engineering tool adjustments - how to add your own activities.

Whenever you use hibernate reveng file to generate your entities - this could be helpfull for you, I spend some time to findout how hib-tool.jar is build  and here some easy-peasy example how to adjust them. How to create some additional parameters automatically on entity mapping level.

Basically hib-tool internally uses ftl - FreeMarker Template language. Short introduction to it you could find here:

This post is not about ftl but how simply you can adjust reveng tool, let's start with some easy-funny change to give you heads up:
Lets change default comment for auto generated entities, to something that will tell everybody that you was there ;-) 

As tool is responsible for generating pojo classes from tables existing in DB, file that we want to change will be:

${pojo.getClassJavaDoc(pojo.getDeclarationName() + " generated by hbm2java a little bit modified by yarenty.", 0)}
<#include "Ejb3TypeDeclaration.ftl"/>
${pojo.getClassModifiers()} ${pojo.getDeclarationType()} ${pojo.getDeclarationName()} ${pojo.getExtendsDeclaration()} ${pojo.getImplementsDeclaration()}

Example output: ;-)

* Model generated by hbm2java a little bit modified by yarenty. */

Real life example: 

We want to add property on the column level to make sure that this column will not be update-able by hibernate [immutable on DB level].
So if you look into reveng.xml file we would like to add attribute here, lets introduce it as "update-disabled".

<table name="out_model" class="com.yarenty.core.persistence.entities.out.Model" schema="dev" catalog="out_model_dev">
<meta attribute="extra-import">javax.persistence.EntityListeners</meta>
<meta attribute="class-description">
Example Model.
@author Automatic Seam Generator (updated by yarenty)
<meta attribute="scope-class">
<primary-key><generator class=""><param name="sequence_name">market_sequence</param><param name="increment_size">10</param></generator></primary-key> <column name="result">
<meta attribute="update-disabled"/></column>

OK, we wrote it but real thing is: how to make it work?
We need to change two files - one responsible for processing xml, second for processing DB (hbm).
In file: pojo/Ejb3PropertyGetAnnotation.ftl we need to add another property

<#if ejb3>
<#if pojo.hasIdentifierProperty()>
<#if property.equals(clazz.identifierProperty)>
<#-- if this is the id property (getter)-->
<#-- explicitly set the column name for this property-->
<#if pojo.hasMetaAttribute(property, "update-disabled")>

And now in file: hbm/property.hbm.ftl when output java class will be created we need to add our output text that we want to see: 

<#if !property.updateable> update="false"</#if> <#if !property.insertable> insert="false"</#if> <#if !property.basicPropertyAccessor>

So our output, will be:

@Column(name = "result", updatable = false, length = 1) public Character getResult() { return this.result; }

TIP: As you can see - highlighted in yellowish - there is quite similar method to avoid insertion of column.