Hibernate Reverse Engineering Tips

Hibernate Reverse Engineering is used to generate hibernate POJO classes from the database schema. I recently got a task to create POJO classes for one of our projects. The task required generation of annotated java classes based on the schema definition. One of the main issues I faced during the task is the lag of proper Javadocs for hibernate tools related classes. Also, I couldn’t find quick reference for some of the basic conversions. Some reference is available for conversions using a reveng.xml file or using meta-tags in the hbm.xml files, but, if you are not willing to create hbm.xml files in your project and want to go the annotation way, your path is tough.  So, I thought of writing this article to provide some basic tips for developers who are stuck with similar issues. This blog does not deal with setting up reverse engineering configuration or a step by step documentation.

1. Setting up Reverse Engineering Strategy:

After you have set up your hibernate console configuration, its time to define your reverse engineering strategy. You need to create a class that will extend any of the reverse engineering classes like ‘DelegatingReverseEngineeringStrategy’, ‘DefaultReverseEngineeringStrategy’. In this class, you will override methods to define your strategy. Lets name the class ‘MyReverseEngineeringStrategy’.

public class MyReverseEngineeringStrategy extends DelegatingReverseEngineeringStrategy {
  public MyReverseEngineeringStrategy(ReverseEngineeringStrategy delegate) {
    super(delegate);
  }

  -----
}

2. Configure class name based on table name

To setup a naming strategy for your generated class, you need to override ‘tableToClassName’ method in the above class. For example, if your table names start with ‘abc_’ and you wish to create java files without this prefix, you can override this method

  public String tableToClassName(TableIdentifier tableIdentifier) {
    String fullClassName = super.tableToClassName(tableIdentifier);
    String packageName = fullClassName.substring(0,fullName.lastIndexOf(".")+1);
    String className = fullClassName.substring(fullName.lastIndexOf(".")+1);
    if(className.startsWith("Abc")) {
      className = className.substring(3); 
      return packageName + className;
    } else
      return className;
  }

You can also add multiple filters based on the class names fetched from TableIdentifier.

3. Configure Java type based on database type

If you want to define custom java data types corresponding to a particular SQL type, for ex, if your table uses ‘Timestamp’ as sql type for all dates, reverse engineering will generate ‘java.util.Date’ as the java data type by default. If you rather wish to generate ‘java.sql.Timestamp’ as the java data type in the generated classes, you need to override the ‘columnToHibernateTypeName’ method.

  public String columnToHibernateTypeName(TableIdentifier table,
      String columnName,
      int sqlType,
      int length,
      int precision,
      int scale,
      boolean nullable,
      boolean generatedIdentifier) {
    if (sqlType == java.sql.Types.TIMESTAMP) {
      return "Timestamp";
    }
    else {
      return super.columnToHibernateTypeName(table, columnName, sqlType, length,
        precision, scale, nullable, generatedIdentifier);
    }
  }

You can also setup filters in this method based on other parameters like ‘column name’, ‘length’ etc.

4. Adding Meta attributes

Defining your reverse engineering strategy allows you to add various meta attributes to your generated classes. For this, you need to override ‘tableToMetaAttributes’ method in the above class. The code below shows adding various attributes like ‘implements’, ‘extends’ and ‘javadocs’. The full list of allowed meta attributes can be referred from here.

public Map<String, MetaAttribute> tableToMetaAttributes(TableIdentifier tableIdentifier) {

    @SuppressWarnings("unchecked")
    Map<String, MetaAttribute> metaAttributes = super.tableToMetaAttributes(tableIdentifier);

    if(metaAttributes == null) {
      metaAttributes = new HashMap<String, MetaAttribute>();
    }

    // Each generated class will implement java.lang.Runnable interface
    MetaAttribute implementsAttribute = new MetaAttribute("implements");
    implementsAttribute.addValue("java.lang.Runnable");
    metaAttributes.put("implements", implementsAttribute);

    // All generated classes will extend com.abc.Test class
    MetaAttribute extendsAttribute = new MetaAttribute("extends");
    extendsAttribute.addValue("com.abc.Test");
    metaAttributes.put("extends", extendsAttribute);

    // Adds the javadoc on top of each file.
    MetaAttribute javadocsAttribute = new MetaAttribute("class-description");
    String description = "Hibernate Entity for table " + tableIdentifier.getName()
        +"\n" + "\n" + "@author Vikram Batra";
    javadocsAttribute.addValue(description);
    metaAttributes.put("class-description", javadocsAttribute);

    return metaAttributes;

  }

You can also add various filters based on the table name in the above method.

5. Adding extra imports

I could not find any ways of adding extra import statements  to the generated files using any of the methods in the above class. I needed an extra import for making sure the ‘Timestamp’ type added in step 3 above works. To add the extra import to the generated files, simply put a statement in the hibernate.reveng.xml file. Add filters in the table filter tag.

<hibernate-reverse-engineering>

<table-filter match-name=".*" match-schema=".*" match-catalog=".*">

<meta attribute="extra-import">java.sql.Timestamp</meta>

</table-filter>
</hibernate-reverse-engineering>

6. Adding extra annotations to the class

I implemented Auditing in the project using hibernate envers. To enable auditing on an entity, I need to add ‘@Audited’ annotation to all my generated classes. This can be done by adding following statements in the hibernate.reveng.xml

<hibernate-reverse-engineering>

<table-filter match-name=".*" match-schema=".*" match-catalog=".*">

<meta attribute="extra-import">org.hibernate.envers.Audited</meta>

<meta attribute="scope-class">@Audited</meta>

</table-filter>

</hibernate-reverse-engineering>

I hope these tips help you create your reverse engineering strategy with hibernate. You can find the complete code for this experiment on github.

Post your comments if you wish to share your experiences.

@Facebook

Subscribe to Blog via Email

Quick Enquiry

2 thoughts on “Hibernate Reverse Engineering Tips

  1. Thanks for your comments John. Any appreciation is good motivation for us. Feel free to share your experiences with Reverse Engineering here and we’ll be happy to update the post.

Leave a Reply

Your email address will not be published. Required fields are marked *