In the article Java Hibernate Reverse Engineering Tutorial with Eclipse and MySQL, you learn how to use Hibernate Tools (a part of JBoss Tools) plug-in in Eclipse to generate code (model classes, mapping files, DAO code) from tables in a database, using the default reverse engineering strategy which is, of course, may not be enough in some cases.

What if you want to exclude some tables, change types mapping, generate equals() and hashCode(), generate toString()… and save this strategy to be reused whenever you run the code generation?

Fortunately, the Hibernate Tools plug-in in Eclipse allows you to customize and control the code generation in finer details using either XML configuration (via the hibernate.reveng.xml file) or Java code (by supplying a custom strategy class).

So in this article, you will learn how to customize, and more, control the code generation process of the Hibernate Reverse Engineering feature.

The examples in this article are based on the MySQL database schema used in the article Java Hibernate Reverse Engineering Tutorial with Eclipse and MySQL.

 

1.Customize Code Generation by using hibernate.reveng.xml file

When running Hibernate code generation, you can supply an XML file called hibernate.reveng.xml that allows you to control the reverse engineering process in various options: schema selection, type mappings, table filters, columns, primary keys, foreign keys, etc.

In the Hibernate Code Generation Configurations dialog, you can provide the hibernate.reveng.xml file by clicking the Setup button, as shown below:

Locate hibernate reveng xml file



 

You can choose an existing file or create a new one:

setup reverse engineering

 

Click Create new… Select where to put the file (here I choose the project’s root directory):

Create reveng xml locate file

 

Click Next. In the screen Configure Table Filters, you can specify which tables can be included/excluded from code generation.

- Choose a Hibernate configuration file under Console configuration.

- Click Refresh to load the database schema. You can expand the tree on the right, choose a table to be exclude, and click Exclude. Here I choose to exclude the table user:

Configure Table filters

 

Click Finish, and click Run. You can see under the specified package, there are only two model classes that have been generated, Category and Product. The table user is excluded from the reverse engineering process so there’s no model class generated for that table.

Open the hibernate.reveng.xml file you can see its XML content (click the Source tab):

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

<hibernate-reverse-engineering>
  <table-filter match-catalog="mysales" match-name="user" exclude="true"/>
</hibernate-reverse-engineering>
 

You can realize that the Hibernate Reverse Engineering Editor has several tabs that allow you to specify the configurations visually (very convenient for programmers). The following screenshot shows the visual editor for table filters:

Reveng Editor

 

As you can see, you can use the visual editors for type mappings, table filters and tables & columns. For other configurations, you have to edit the XML code directly (with code suggestion supported).

 

Schema selection

If the connection returns multiple schemas (in case of MySQL, the database URL has no schema name e.g. jdbc:mysql://localhost:3306/), you can use the <schema-selection> tag to specify which schemas to be processed. For example:

<schema-selection match-catalog="sales"/>
This processes only the schema name (database name) “sales” in MySQL database. In another RDBMS, you might have to use the match-schema attribute:

<schema-selection match-schema="sales"/>
The following statement tells Hibernate Tools to do reverse engineering only on tables that start with “order” in the database “sales”:

<schema-selection match-catalog="sales" match-table="order.*"/>
 

Type mappings

You can use the <type-mapping> section with <sql-type>tag to specify how JDBC types found in the database should be mapped to Hibernate types in Java. For example, the following XML will generate Java fields of type Long from columns of type INTEGER in the database:

<type-mapping>
	<sql-type jdbc-type="INTEGER" hibernate-type="Long" />
</type-mapping>
The generated code would be like this (the result of reverse engineering of the table “Category”):

/**
 * Category generated by hbm2java
 */
@Entity
@Table(name = "category", catalog = "mysales")
public class Category implements java.io.Serializable {

	private Long categoryId;
	
	....
}
Note that the value of the jdbc-type attribute must be a type of java.sql.Types. (see SQLType).

 

Table Filters

The <table-filter>tag lets you specify tables to be excluded or included in the reverse engineering, following some matching rules. For example, the following statement tells Hibernate Tools does not process the table “user” in the database “mysales” during the reverse engineering (exclude = “true”):

<table-filter match-catalog="mysales" match-name="user" exclude="true"/>
But the following statement processes only the table “user”:

<table-filter match-catalog="mysales" match-name="user" exclude="false"/>
The following XML processes tables having prefix “pro” and put the generated model classes under the specified package:

<table-filter match-name="pro.*" exclude="false" package="com.mycompany.products" />
 

Specific Table Configuration

The <table> tag lets you control at greater details how a table should be reversed engineered: table name, class name, primary column, foreign key column, and individual columns. Here is the syntax of the <table> tag:

<table 
 	catalog="catalog_name"
	 schema="schema_name"
	 name="table_name"
	 class="ClassName"
	>
	 <primary-key.../>
	 
	 <column.../>
	 
	 <foreign-key.../>
</table>
For more details, please consult the Hibernate Tools documentation Controlling reverse engineering.

 

2. Customize Code Generation by using a Custom Strategy Class

Besides using XML in the hibernate.reveng.xml file, you can also customize the code generation by Java code. This can be done by creating a Java class that implements the ReverseEngineeringStrategyor extends the DelegatingReverseEngineeringStrategyclass (both are in the package org.hibernate.cfg.reveng).

It’s recommended to extend the DelegatingReverseEngineeringStrategy class to implement only the relevant methods. For example, let’s see the following custom strategy class:

/** Copyright CodeJava.net To Present
All rights reserved. 
*/
package net.codejava;

import org.hibernate.cfg.reveng.DelegatingReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.ReverseEngineeringStrategy;
import org.hibernate.cfg.reveng.TableIdentifier;

public class CustomStrategy extends DelegatingReverseEngineeringStrategy {

	public CustomStrategy(ReverseEngineeringStrategy delegate) {
		super(delegate);
	}
	
	@Override
	public String columnToPropertyName(TableIdentifier table, String column) {
		if (column.endsWith("_id")) {
			return "id";
		} else {
			return super.columnToPropertyName(table, column);
		}
	}

	@Override
	public boolean excludeColumn(TableIdentifier table, String columnName) {
		if (columnName.endsWith("_on")) {
			return true;
		} else {
			return super.excludeColumn(table, columnName);
		}
	}
	
	@Override
	public boolean excludeTable(TableIdentifier table) {
		if (table.getName().startsWith("stat")) {
			return true;
		} else {
			return super.excludeTable(table);
		}
	}	
}
As you can see, this class overrides the following methods:

- columnToPropertyName(): specifies how columns should be mapped to property names. In this strategy, we shorten all the column names ending with “_id” to just “id”.

- excludeColumn(): specifies matching rules to exclude columns from being reversed engineering. In this strategy, we exclude all column names ending with “_on”.

- excludeTable(): specifies matching rules to exclude tables from being reversed engineering. In this strategy, we exclude all table names starting with “stat”.

And in the Hibernate Code Generation Configurations dialog, specify fully qualified class name of the strategy class as follows:

Specify Custom Strategy

 

Click Run to perform the reverse engineering, and then check the generated code in the specified package.

NOTE: Using a custom strategy class requires the Hibernate Tools JAR file to be present in the project’s classpath. You can add a dependency in Maven’s POM file, but it requires several dependencies related to Eclipse runtime, which is not necessary. So it’s recommend to add a reference to Hibernate Tools JAR file which can be found in the following path under Eclipse’s installation directory:

eclipse\configuration\org.eclipse.osgi\1049\0\.cp\lib\hibernate-tools-5.2.8.Final.jar
As shown below in the Java Build Path section of the project’s Properties screen:

Java Build Path

And for your reference, the following list contains some methods in the DelegatingReverseEngineeringStrategy class which you can override:

  • columnToHibernateTypeName()
  • columnToMetaAttributes()
  • columnToPropertyName()
  • excludeColumn()
  • excludeForeignKeyAsCollection()
  • excludeForeignKeyAsManytoOne()
  • excludeTable()
  • foreignKeyToAssociationInfo()
  • foreignKeyToCollectionName()
  • foreignKeyToEntityName()
  • foreignKeyToInverseAssociationInfo()
  • foreignKeyToInverseEntityName()
  • foreignKeyToManyToManyName()
  • tableToClassName()
  • tableToCompositeIdName()
  • tableToIdentifierPropertyName()
  • tableToMetaAttributes()
You can use Eclipse’s code auto completion feature (Ctrl + Space) to find these methods.

 

3. Customize POJO Code Generation using <meta> Tag

What if you want to generate equals(), hashCode(), toString(), your own comments,… or any custom code in the POJO model classes? To do so, you can use the <meta> tag in the Hibernate Reverse Engineering XML file hibernate.reveng.xml. Let’s see some examples.

 

Generate equals() and hashCode() methods:

Add the following <meta> tag inside a <column> tag of a <table> section to specify that the column will be used in the code of equals() and hashCode() methods:

<meta attribute="use-in-equals">true</meta>
For example, the following XML code tells Hibernate Tools to use the column category_id in the code of equals() and hashCode() methods in the POJO class reversed engineering from the table category:

<table catalog="mysales" name="category">
	
	<column name="category_id">
		<meta attribute="use-in-equals">true</meta>
	</column>
	
</table>
And you can see the generated code for equals() and hashCode() in the Category class looks like this:

public boolean equals(Object other) {
	if ((this == other))
		return true;
	if ((other == null))
		return false;
	if (!(other instanceof net.codejava.hibernate4.Category))
		return false;
	net.codejava.hibernate4.Category castOther = (net.codejava.hibernate4.Category) other;

	return ((this.getCategoryId() == castOther.getCategoryId()) || (this.getCategoryId() != null
			&& castOther.getCategoryId() != null && this.getCategoryId().equals(castOther.getCategoryId())));
}

public int hashCode() {
	int result = 17;

	result = 37 * result + (getCategoryId() == null ? 0 : this.getCategoryId().hashCode());

	return result;
}
So to add more columns/properties involved in the equals() and hashCode() calculation, just add relevant <meta> tag like the above example.

 

Generate toString() method:

Similarly, add the following <meta> tag inside a <column> tag to use the column in toString() method:

<meta attribute="use-in-tostring">true</meta>
For example:

<table catalog="mysales" name="product">
	<column name="name">
		<meta attribute="use-in-tostring">true</meta>				
	</column>
</table>
And the generated code looks like this:

public String toString() {
	StringBuffer buffer = new StringBuffer();

	buffer.append(getClass().getName()).append("@").append(Integer.toHexString(hashCode())).append(" [");
	buffer.append("name").append("='").append(getName()).append("' ");
	buffer.append("]");

	return buffer.toString();
}
 

Generate comments for class description and field description:

The following <meta> tag will generate comment for the class description:

<table catalog="mysales" name="category">
	<meta attribute="class-description">
		A category that contains related products.
	</meta>
</table>
 

And the generated code looks like this:

/**
 * 			A category that contains related products.
 * 		
 */
@Entity
@Table(name = "category", catalog = "mysales")
public class Category implements java.io.Serializable {
	...
}
Similarly, specify the following XML to generate comment for a field:

<column name="price">
	<meta attribute="field-description">
		Price of the product in USD. 
	</meta>
</column>
 

Generate your own code:

The following XML adds extra code that is inserted at the end of the class:

<table catalog="mysales" name="product">
	<meta attribute="class-code">
		private void myMethod(String s) {
			System.out.println(s);
		} 
	</meta>	
</table>
And the generated code looks like this:

// The following is extra code specified in the hbm.xml files

private void myMethod(String s) {
	System.out.println(s);
}

// end of extra code specified in the hbm.xml files
For more customization, refer to the document Controlling reverse engineering

NOTE: If you want to have total control of code generation, edit the Freemarker Templates (.ftl files) which can be found under the package pojo in Hibernate Tools JAR file.

 

Other Hibernate Tutorials:


About the Author:

is certified Java programmer (SCJP and SCWCD). He started programming with Java in the time of Java 1.4 and has been falling in love with Java since then. Make friend with him on Facebook and watch his Java videos you YouTube.



Add comment

   


Comments 

#3Agnes2020-04-28 06:16
I tried doing reverse engineering in intellij but the pojo classes created are not mapped properly and the facilities that ecllipse provides is not found in intellij. I cannot switch to another platform too
Quote
#2Nam2019-10-15 04:30
Quoting Alex:
is it possible to generate entities in this form?:... {

Hmm. I'm not sure. You should look at the official document to know more:
docs.jboss.org/.../reverseengineering.html
Quote
#1Alex2019-10-14 15:59
Thanks for the article!
is it possible to generate entities in this form?:
@Entity
@Table(name = "category", catalog = "mysales")
public class Category extend BaseEntity implements java.io.Serializable {
Quote