Implementing a Custom Naming Strategy With Hibernate

As all of you who are familiar with Hibernate know, not all entity annotations are mandatory. These non mandatory annotations include @Table and @Column annotations. However, even though these annotations are not required, leaving them out has never been an option for me. I simply don't like the table and column names which are generated by Hibernate unless they are explicitly set.

The naming convention of database objects and schema elements is controlled by the used implementation of the org.hibernate.cfg.NamingStrategy interface. Hibernate 3.6 has four implementations of this interface:

However, none of these implementations fulfill my requirements which are:

  • All characters must be lowercase.
  • Table names must be in plural form.
  • Words must be separated by using an underscore.

Since the ImprovedNamingStrategy class is almost what I am looking for (its only fault is that it returns the table name in a singular form), I decided to create a custom naming strategy by extending it and overriding its classToTableName() method. The source code of my implementation is given in following:

package net.petrikainulainen.hibernate.util;
import org.hibernate.cfg.ImprovedNamingStrategy;

/**
 * A custom naming strategy implementation which uses following naming conventions:
 * <ul>
 *     <li>Table names are lower case and in plural form. Words are separated with '_' character.</li>
 *     <li>Column names are lower case and words are separated with '_' character.</li>
 * </ul>
 * @author Petri Kainulainen
 */
public class CustomNamingStrategy extends ImprovedNamingStrategy {

    private static final String PLURAL_SUFFIX = "s";

    /**
     * Transforms class names to table names by using the described naming conventions.
     * @param className
     * @return  The constructed table name.
     */
    @Override
    public String classToTableName(String className) {
        String tableNameInSingularForm = super.classToTableName(className);
        return transformToPluralForm(tableNameInSingularForm);
    }

    private String transformToPluralForm(String tableNameInSingularForm) {
        StringBuilder pluralForm = new StringBuilder();

        pluralForm.append(tableNameInSingularForm);
        pluralForm.append(PLURAL_SUFFIX);

        return pluralForm.toString();
    }
}

The next step is to configure the Hibernate to use my custom naming strategy. If you are using Hibernate, you can either

  1. You can set a reference to the custom naming strategy by calling the setNamingStrategy() method of the Configuration class as described in the Implementing a Naming Strategy Section of the Hibernate Reference Documentation.
  2. You can set the value of hibernate.ejb.naming_strategy property to net.petrikainulainen.hibernate.util.CustomNamingStrategy in the Hibernate XML configuration file as described in the XML Configuration Section of the Hibernate Reference Manual.

If you are using JPA, you can set the used naming strategy by setting the value of hibernate.ejb.naming_strategy property to net.petrikainulainen.hibernate.util.CustomNamingStrategy in the persistence.xml as described the Packaging Section of the Hibernate EntityManager reference manual.

After you have configured Hibernate to use the implemented custom naming strategy, you can remove the @Table and @Column annotations from entity classes (This is not entirely true but I will describe the shortcomings of my solution later). For example, if you have an entity class Person, its source code could look something like this:

@Entity
@Table("persons")
public class Person {

	@Column(name="first_name")
	private String firstName;

  	@Column(name="last_name")
  	private String lastName;

	public Person() {
	
	}
}

After Hibernate is using the new naming strategy, the source code of the Person entity would look like this (but Hibernate would still use the same table and column names which were explicitly specified in the previous example):

@Entity
public class Person {

	private String firstName;

  	private String lastName;

	public Person() {
	
	}
}

I have now described to you how you can implement and configure a custom naming strategy with Hibernate. However, the solution described in this blog entry is far from perfect. It has following shortcomings:

  • It does not always produce grammatically correct table names. For example: The plural form is a word entity is not entitys. It is entities. This problem is pretty hard to tackle automatically but remember that you can always use the @Table annotation to solve these cases.
  • If you want to add restrictions to the column in the entity class, you still have to add the @Column annotation. This is not a problem to me because I always generate the database creation scripts manually and add constraints to the database. However, if you want to generate your database by using Hibernate, you would have to specify the constraints by using the @Column annotation or add the needed constraints manually to the created database.
  • You still have to configure the relationships between entities by using annotations. Creating an automatic solution for this problem would mean that I would have to invent some kind of naming convention for the names of join tables and columns. This is something which I am not willing to do. However, If you have an another solution in mind, let me know!
16 comments… add one
  • Kuba Apr 30, 2013 @ 20:33

    Thanks! Great article :)

    • Petri May 1, 2013 @ 1:47

      You are welcome. I am happy to hear that you liked it.

  • Fran Serrano Pons Sep 30, 2013 @ 9:39

    Really nice to know about this Petri. Really simple and useful to avoid being using hard-coded names all around.

    • Petri Sep 30, 2013 @ 19:44

      Hi Fran,

      I am happy to hear that this blog post was useful to you. On the other hand, I have changed my mind about about JPA annotations. Nowadays I add them in any case because I think that they provide useful documentation to other developers.

      Also, if you run integration tests by using the create-drop schema generation strategy, you must specify the restrictions in the database creation scripts and in the domain model. Otherwise your integration tests are run against a database which doesn't match to your production database. This sounds a bit too risky to me.

  • Andres Feb 15, 2014 @ 6:08

    I have a problem. What if I want to prefix my property name with the table name? Couldn't find a way to access tale name from property name methods.

  • Petri Feb 17, 2014 @ 19:55

    I took a quick look at the Javadocs of the ImprovedNamingStrategy class and the NamingStrategy interface, and it seems that this is not possible (There are some methods which provide table names as method parameters but I assume that you are talking about "regular" columns).

  • Slava Semushin Apr 5, 2014 @ 20:27

    Thanks for the artice. I just tried to use org.hibernate.cfg.ImprovedNamingStrategy in my pet project, but found out that in this case I need to explicitly specify @JoinColumn with column name :-( I mean that before I write:

    @ManyToOne
    private Country country;

    but now I need to write

    @ManyToOne
    @JoinColumn(name = "country_id")
    private Country country;

    And it's stop me to use this feature.

    • Petri Apr 6, 2014 @ 11:31

      You are welcome. I am happy to hear that this blog post was useful to you.

      These different naming strategies are indeed a bit confusing. At the moment I use the ImprovedNamingStrategy and specify the column names myself. It is a bit frustrating but somehow I have feeling that it is the least painful way to do this.

  • fernando Jan 30, 2015 @ 0:51

    Hi I am looking for a solution just to have MyTableAndColumName to my_table_and_column_name.

    I see your example uses plural but I only need the basic stuff. Do you know any spring/hibernate solution to use and reach this goal?

    PLMK

    • Petri Jan 31, 2015 @ 20:31

      Unfortunately I don't know how you can do this. The problem is that the NamingStrategy interface doesn't provide the name of the database table as a method parameter to the methods that are used to create the column names. That is why I assume that this cannot be done.

  • Frank Feb 3, 2015 @ 7:39

    Thanks for the use full article. I've implemented as you described, but the CustomNamingStrategy() method get called only when I deploy the WAR file. At what point and how should I call CustomNamingStrategy method to overwrite the table name?

    I would like call in my service class before the DAO class instantiated and pass the table name as a parameter. Your help would appreciated.

    • Petri Feb 4, 2015 @ 20:30

      Hi,

      As far as I know, you cannot call the custom naming strategy from your own code. You can only use it to change the naming conventions that are used by Hibernate (i.e. Hibernate uses this component when it creates names for database tables and table columns).

      Why do you want to call it from your service class? If you let me know what you want to do, I might be able to help you to find a good solution to your problem.

  • sridhar May 25, 2015 @ 15:26

    Is there a way to customize sequence table name as well. Thanks

  • Raki Mar 7, 2016 @ 7:24

    Weather this example is used to assign the entity name at runtime.

    • Petri Mar 9, 2016 @ 16:50

      No. It is used to automatically create the name of the database table and the names of the database columns.

Leave a Reply