pátek 15. května 2015

Hibernate 4.3.7 patch for schema name customization

The JPA standard allows to hardly define a concrete schema for tables/entites via annotations (for example @Table). For my project was necessary to modify these shema names according to configuration on the realtime, just before EntityManagerFactory is created. Generally, the Hibernate version 4.3.7 provides for a db-to-java name mapping special interface org.hibernate.cfg.naming.NamingStrategyDelegate.

This interface provides lots of nice method for define a mapping between JPA objects names and db objects names, but one thing is missing - schema names customization.

Extending interface

For assurance of backward compatibility, I decided to create new interface as extended existing interface:

package org.hibernate.cfg.naming;
public interface ExtendNamingStrategyDelegate extends NamingStrategyDelegate {
  public String determineSchemaName(String schemaName);
}

Modification of internal behavior of hibernate was not easy. All names modifications is present in very extensive class org.hibernate.cfg.AnnotationBinder. This class contains cca 2800 lines of code and really needs to be refactored :). I added this code fragment on multiple places:

NamingStrategyDelegate n =
  mappings.getNamingStrategyDelegator().getNamingStrategyDelegate(false);

if (n instanceof ExtendNamingStrategyDelegate) {
  schema = ((ExtendNamingStrategyDelegate) n).determineSchemaName(schema);
  if (schema == null) {
    schema = "";
  }
}
If you want to see whole class, please download sourcecode.

Patching of original hibernate

The Hibernate framework is opensource and for building purposes is used the Gradle system. Unfortunately, I haven't any knowledges about Gradle and also our processes in company are hardly maven-oriented. I've decided to do it "dirty" way with 2 maven projects.
  1. hibernate-core-patch (version 4.3.7.1) - contains my created class ExtendNamingStrategyDelegate and modified AnnotationBinder only.  Project version 4.3.7.1 defines that patch is based on hibernate 4.3.7.
  2. hibernate-core (version 4.3.7.1-Patched)- Combination of original hibernate binaries (hibernate-core version 4.3.7) and forced injection of my modifications (hibernate-core-patch 4.3.7.1). This project does not contain any java code and it is defined as a integrator for binaries via maven-dependency-plugin.
Download sourcecode here.

Using of patch

After building and installing patched hibernate-core project, Use in your project patched version of hibernate-core instead of original (replace version 4.3.7 with 4.3.7.1-Patched).

For using NamingStrategyDelegate, please read original documentation

https://docs.jboss.org/hibernate/orm/4.3/manual/en-US/html/ch03.html#configuration-namingstrategy

With difference that you will use ExtendedNamingStrategyDelegate interface.

Summary

I'm not a fan of "raping" of frameworks, tools and standard procedures as shows this article:). But sometimes it can be very usefull and it can save lots of time before you find better way to solve a problem. In this time, Hibernate version 5 is comming and according to release notes, it should be refactored and also support for schema name mapping should be added.