Skip to main content

Reverse Engineering and Code Generation

· 6 min read

The goal of this post is to explain how to model a database into java pojo classes with EJB or JPA annotations using reverse engineering. We can use several tools such as MinuteProject or Mogwai ERDesignerNG. In this post we are going to use JBoss Tools plugins for Eclipse (Hibernate Tools). With this tool not only can you configure files using JPA and EJB annotations, but also other annotations such as OpenXava.

The following images are from a JBoss Tools 4.2.1 Final installed into an Eclipse Luna.

Firstly, you have to download JBoss Tools from here. As an example of database, we are to going to use Classic Models which can be downloaded from this page.

JPA Project

After installing JBoss Tools plugin and ClassModels database, the first thing you have to do is to create a new JPA project, because this code is going to be used, for example, in a OpenXava project, with JPA annotations and Hibernate 4.3.

The name of our project is ClassicModels, running in a Java SE 1.8 and JPA 2.1.

In this project we do not use other target runtimes, such as Apache Tomcat v7, because the code of this project is going to be copied to an OpenXava project, where all the libraries needed, such as JPA, database libraries and so on, are already configured.

Then you click on Next button twice an complete the following page.

The JPA implementation is left disabled on purpose because, as it was said above, the code of this project is going to be copied to, for example, an OpenXava project. For that reason, after creating the JPA project, you will have to add the jpa.jar library from OpenXava sdk and you will have to add the OpenXava project to your java build path.

Hibernate Console

Following the steps mentioned above creating a new JPA project, you will also get a Hibernate console with the same name. Nevertheless, creating a new Hibernate console from scratch is a good idea. For that, in Eclipse go to Window - Open Perspective - Other - Hibernate. Then go to File - New Hibernate Console Configuration.

After completing the main fields as it is shown in the followin image

you have to click on New... button in order to create the connection to ClassicModels database.

If you have not defined a Driver Template previously, you will have to specify a Driver Template and to define a name clicking on the button New driver definition. In our case, we use a previous definition.

The summary of the new connection profile is

You have to take into account that you need a valid META-INF/persistence.xml in your classpath to avoid the error: Persistence unit not found: 'null'. If you have a well-configured persistence.xml, you will be able to select, for example, ClassicModels persistence unit.

Now you can open Database node in the Hibernate Configurations view.

Hibernate Reverse Engineering File

The next step is to built a new Hibernate Reverse Engineering File.

After selecting Console configuration, you have to click on Refresh button in order to open the database schema. Then click on Finish.

At the moment, you leave the new file empty.

Hibernate Code Generation Configuration

The last step is to configure Hibernate Code Generation. For that, click on Hibernate Code Generation Configurations... as it is shown in the following picture:

This button is only found in Hibernate perspective, unless you have explicitly configure your favourite perspective.

Complete the next page:

Next complete Exporters, Refresh and Common tabs:

Finally, click on Apply and Run buttons.

You can now see all the new classes:

Fine tune table/column mappings and annotations

So far you have left hibernate.reveng.xml practically empty. You can modify this file using the reveng.xml wizard and associated editor. These tools allow you to tweak many aspects for controlling the reverse engineering.

  • include/exclude of tables
  • overrides for column types, values and keys
  • customize mapping of JDBC types to hibernate types

However, in some cases, you can want to add special annotations, or to change e.g. fetch type, instead of LAZY, you want EAGER. For these cases, reveng.xml is not enough and you have to use freemarker templates.

As an example, you want that in Classic Models the column image of the table Productlines to be shown as an image, and the relation between Productlines and Products must be EAGER instead of LAZY.

In short, you want that the automatic code generated in Productlines.java

  @Column(name = "image")
public byte\[\] getImage() {
return this.image;
}

public void setImage(byte\[\] image) {
this.image = image;
}

@OneToMany(fetch = FetchType.LAZY, mappedBy = "productlines")
public Set<Products> getProductses() {
return this.productses;
}

public void setProductses(Set<Products> productses) {
this.productses = productses;
}

must be converted to

  @Column(name = "image")
@Stereotype("PHOTO")
public byte\[\] getImage() {
    return this.image;
  }

  public void setImage(byte\[\] image) {
    this.image = image;
  }

  @OneToMany(fetch = FetchType.EAGER, mappedBy = "productlines")
  public Set<Products> getProductses() {
    return this.productses;
  }

  public void setProductses(Set<Products> productses) {
    this.productses = productses;
  }

in reverse engineering processes.

First of all, you have to extract to a folder files with extension .flt (freemarker) from the file hibernate-tools.jar located in the plugins directory of your Eclipse. In my case, this file is at

plugins/org.hibernate.eclipse.libs_4.0.1.Final-v20150324-2307-B95/lib/tools/hibernate-tools-3.4.0.CR2.jar

Extract these file under resources folder of the ClassicModels project.

Next you have to configure your ClassicModelsCodeGeneration for using custom templates.

Then you have to edit Ejb3PropertyGetAnnotation.ftl in order to add @Stereotype and to change FetchType.

<#if ejb3>
<#if pojo.hasIdentifierProperty()>
<#if property.equals(clazz.identifierProperty)>
${pojo.generateAnnIdGenerator()}
<#-- if this is the id property (getter)-->
<#-- explicitly set the column name for this property-->
</#if>
</#if>

<#if c2h.isOneToOne(property)>
${pojo.generateOneToOneAnnotation(property, cfg)}
<#elseif c2h.isManyToOne(property)>
${pojo.generateManyToOneAnnotation(property)}
<#--TODO support optional and targetEntity-->
${pojo.generateJoinColumnsAnnotation(property, cfg)}
<#elseif c2h.isCollection(property)>

<#if property.name == "productses">
@OneToMany(fetch = FetchType.EAGER, mappedBy = "productlines")
<#else>
${pojo.generateCollectionAnnotation(property, cfg)}
</#if>

<#else>
${pojo.generateBasicAnnotation(property)}
${pojo.generateAnnColumnAnnotation(property)}
<#if property.name == "image">
@Stereotype("PHOTO")
</#if>
</#if>
</#if>

You will also have to edit hibernate.renveng.xml to add the new import that are needed for @Stereotype and for the relation.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-reverse-engineering PUBLIC "-//Hibernate/Hibernate Reverse Engineering DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-reverse-engineering-3.0.dtd" >

<hibernate-reverse-engineering>

<table catalog="classicmodels" name="productlines">
<meta attribute="extra-import">
javax.persistence.FetchType
</meta>
<meta attribute="extra-import">
javax.persistence.OneToMany
</meta>
<meta attribute="extra-import">
org.openxava.annotations.Stereotype
</meta>
</table>

</hibernate-reverse-engineering>

For sake of simplicity, in this blog we have only used @Stereotype annotation, but, obviously, we could have used other annotations such as @View, @Tab and son on.

Summary

This blog post has taught us:

  • How to create a Hibernate Console in Eclipse
  • How to configure a Hibernate reverse engineering file
  • We can now generate model classes from a database
  • We can now add annotations from third parties, such as OpenXava, and change default annotations, using freemarker templates

You can get more information at http://docs.jboss.org/tools/latest/en/hibernatetools/html/index.html

Related posts

P.S. You can get the example of this blog post from Github.