Hibernate naming policy details

  • 2020-06-01 09:46:45
  • OfStack

The naming strategy of hibernate can reduce the maintenance of database identifier naming, and further reduce the amount of repetitive code for this part of the naming to improve maintenance.

There are two types of names for hibernate, one is explicitly named and the other is implicitly named.

1) explicit naming: when mapping configuration, the database table name, column name and so on are set, which is the explicit naming.

2) implicit naming: explicit naming 1 is generally not necessary, so when the name is not set, the implicit naming can be left to hibernate. In addition, implicit naming also includes database identifiers that cannot be explicitly named. The interface ImplicitNamingStrategy is used to implement implicit naming.

3) filter naming: interface PhysicalNamingStrategy is used for one-step filtering processing of explicit or implicit naming.

Example:

TestTable1Impl.java


@Entity
//  Implicitly name the table names 
@Table
public class TestTable1Impl {
  //---------------------------------------------------------------
  // Field
  //---------------------------------------------------------------
  @Id
  @Column()
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long testId;
  @Column(length = 20)
  private String testName;
  @ManyToOne
  private TestTable2Impl testForeign;
  //---------------------------------------------------------------
  // Method
  //---------------------------------------------------------------
  public Long getId() {
    return testId;
  }
  public void setId(Long id) {
    this.testId = id;
  }
  public String getName(){
    return testName;
  }
  public void setName(String name){
    this.testName = name;
  }
  public TestTable2Impl getTestForeign() {
    return testForeign;
  }
  public void setTestForeign(TestTable2Impl testForeign) {
    this.testForeign = testForeign;
  }
}

TestTable2Impl.java


@Entity
//  Explicitly name the table name 
@Table(name = "TestTable2Impl")
public class TestTable2Impl {
  //---------------------------------------------------------------
  // Field
  //---------------------------------------------------------------
  @Id
  @Column()
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  private Long testId;
  @Column(length = 20)
  private String testName;
  //---------------------------------------------------------------
  // Method
  //---------------------------------------------------------------
  public Long getId() {
    return testId;
  }
  public void setId(Long id) {
    this.testId = id;
  }
  public String getName(){
    return testName;
  }
  public void setName(String name){
    this.testName = name;
  }
}

MyImplicitNamingStrategyImpl.java


public class MyImplicitNamingStrategyImpl extends ImplicitNamingStrategyJpaCompliantImpl implements ImplicitNamingStrategy {
  @Override
  public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) {
    Identifier name = super.determinePrimaryTableName(source);
    Identifier result = toStandard(name, "Impl");
    System.out.println("ImplicitNamingStrategy / PrimaryTableName -> \n\t" + name + " => " + result);
    return result;
  }
  private Identifier toStandard(Identifier name, String... removeSuffixes){
    if(removeSuffixes == null)
      return name;
    if(name == null)
      return null;
    String text = name.getText();
    if(removeSuffixes != null){
      for(String suffix : removeSuffixes){
        if(text.endsWith(suffix))
          text = text.substring(0, text.length() - suffix.length());
      }
    }
    return new Identifier(text, name.isQuoted());
  }
  @Override
  public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) {
    Identifier name = super.determineJoinTableName(source);
    System.out.println("ImplicitNamingStrategy / JoinTableName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineCollectionTableName(ImplicitCollectionTableNameSource source) {
    Identifier name = super.determineCollectionTableName(source);
    System.out.println("ImplicitNamingStrategy / CollectionTableName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineDiscriminatorColumnName(ImplicitDiscriminatorColumnNameSource source) {
    Identifier name = super.determineDiscriminatorColumnName(source);
    System.out.println("ImplicitNamingStrategy / DiscriminatorColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineTenantIdColumnName(ImplicitTenantIdColumnNameSource source) {
    Identifier name = super.determineTenantIdColumnName(source);
    System.out.println("ImplicitNamingStrategy / TenantIdColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineIdentifierColumnName(ImplicitIdentifierColumnNameSource source) {
    Identifier name = super.determineIdentifierColumnName(source);
    System.out.println("ImplicitNamingStrategy / IdentifierColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) {
    Identifier name = super.determineBasicColumnName(source);
    System.out.println("ImplicitNamingStrategy / BasicColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) {
    Identifier name = super.determineJoinColumnName(source);
    final String result;
    if ( source.getNature() == ImplicitJoinColumnNameSource.Nature.ELEMENT_COLLECTION || source.getAttributePath() == null ) {
      result = transformEntityName( source.getEntityNaming() );
    } else {
      result = transformAttributePath( source.getAttributePath() );
    }
    System.out.println("ImplicitNamingStrategy / JoinColumnName -> \n\t" + name + " => " + result);
    return toIdentifier( result, source.getBuildingContext() );
  }
  @Override
  public Identifier determinePrimaryKeyJoinColumnName(ImplicitPrimaryKeyJoinColumnNameSource source) {
    Identifier name = super.determinePrimaryKeyJoinColumnName(source);
    System.out.println("ImplicitNamingStrategy / PrimaryKeyJoinColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineAnyDiscriminatorColumnName(ImplicitAnyDiscriminatorColumnNameSource source) {
    Identifier name = super.determineAnyDiscriminatorColumnName(source);
    System.out.println("ImplicitNamingStrategy / AnyDiscriminatorColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineAnyKeyColumnName(ImplicitAnyKeyColumnNameSource source) {
    Identifier name = super.determineAnyKeyColumnName(source);
    System.out.println("ImplicitNamingStrategy / AnyKeyColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineMapKeyColumnName(ImplicitMapKeyColumnNameSource source) {
    Identifier name = super.determineMapKeyColumnName(source);
    System.out.println("ImplicitNamingStrategy / MapKeyColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineListIndexColumnName(ImplicitIndexColumnNameSource source) {
    Identifier name = super.determineListIndexColumnName(source);
    System.out.println("ImplicitNamingStrategy / ListIndexColumnName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineForeignKeyName(ImplicitForeignKeyNameSource source) {
    Identifier name = super.determineForeignKeyName(source);
    String result = null;
    String tableName = source.getTableName().getText();
    if(tableName.startsWith(TableNamingConfig.TABLE_PREFIX))
      tableName = tableName.substring(TableNamingConfig.TABLE_PREFIX.length());
    if(source.getColumnNames().size() == 1){
      result = TableNamingConfig.FOREIGN_KEY_PREFIX + tableName + "_" + source.getColumnNames().get(0).getText();
    } else {
      String columnName = source.getReferencedTableName().getText();
      if(columnName.startsWith(TableNamingConfig.TABLE_PREFIX))
        columnName = columnName.substring(TableNamingConfig.TABLE_PREFIX.length());
      result = TableNamingConfig.FOREIGN_KEY_PREFIX + tableName + "_" + columnName;
    }
    System.out.println("ImplicitNamingStrategy / ForeignKeyName -> \n\t" + name + " => " + result);
    return new Identifier(result, name.isQuoted());
  }
  @Override
  public Identifier determineUniqueKeyName(ImplicitUniqueKeyNameSource source) {
    Identifier name = super.determineUniqueKeyName(source);
    System.out.println("ImplicitNamingStrategy / UniqueKeyName -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier determineIndexName(ImplicitIndexNameSource source) {
    Identifier name = super.determineIndexName(source);
    System.out.println("ImplicitNamingStrategy / IndexName -> \n\t" + name);
    return name;
  }
}

MyPhysicalNamingStrategyImpl.java


public class MyPhysicalNamingStrategyImpl implements PhysicalNamingStrategy {
  @Override
  public Identifier toPhysicalCatalogName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    System.out.println("PhysicalNamingStrategy / catalog -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier toPhysicalSchemaName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    System.out.println("PhysicalNamingStrategy / schema -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    Identifier result = toStandard(name, "tb_");
    System.out.println("PhysicalNamingStrategy / table -> \n\t" + name + " => " + result);
    return result;
  }
  @Override
  public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    System.out.println("PhysicalNamingStrategy / sequence -> \n\t" + name);
    return name;
  }
  @Override
  public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment jdbcEnvironment) {
    Identifier result = toStandard(name);
    System.out.println("PhysicalNamingStrategy / column -> \n\t" + name + " => " + result);
    return result;
  }
  private Identifier toStandard(Identifier name){
    return toStandard(name, null);
  }
  private Identifier toStandard(Identifier name, String prefix){
    if(name == null)
      return null;
    String text = name.getText();
    StringBuffer buffer = new StringBuffer();
    if(prefix != null)
      buffer.append(prefix);
    char[] chars = text.toCharArray();
    for(int i=0, len=chars.length; i<len; i++){
      char c1 = chars[i];
      if(c1 >= 'A' && c1 <= 'Z'){
        if(i > 0 && i + 1 < len){
          if(chars[i + 1] < 'A' || chars[i + 1] > 'Z')
            buffer.append('_');
        }
        c1 = (char) (c1 - 'A' + 'a');
      }
      buffer.append(c1);
    }
    return new Identifier(buffer.toString(), name.isQuoted());
  }
}

TableNamingConfig.java


public class TableNamingConfig {
  public static final String TABLE_PREFIX = "tb_";
  public static final String FOREIGN_KEY_PREFIX = "fk_";
}

spring.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans    http://www.springframework.org/schema/beans/spring-beans.xsd    http://www.springframework.org/schema/context    http://www.springframework.org/schema/context/spring-context-4.1.xsd">
  <!--  Configure data source  -->
  <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
    <property name="driverClass" value="com.mysql.jdbc.Driver"></property>
    <property name="jdbcUrl" value="jdbc:mysql://localhost:3306/test?useSSL=false"></property>
    <property name="user" value="root"></property>
    <property name="password" value="123456"></property>
  </bean>
  <bean id="physicalNamingStrategy" class="test.MyPhysicalNamingStrategyImpl"></bean>
  <bean id="implicitNamingStrategy" class="test.MyImplicitNamingStrategyImpl"></bean>
  <bean id="sessionFactory"    class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan">
      <list>
        <!--  You can add multiple packages  -->
        <value>test</value>
      </list>
    </property>
    <property name="hibernateProperties">
      <props>
        <prop key="hibernate.hbm2ddl.auto">create-drop</prop>
        <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
        <prop key="hibernate.show_sql">true</prop>
        <prop key="hibernate.format_sql">true</prop>
        <prop key="hibernate.temp.use_jdbc_metadata_defaults">false</prop>
      </props>
    </property>
    <property name="physicalNamingStrategy" ref="physicalNamingStrategy"></property>
    <property name="implicitNamingStrategy" ref="implicitNamingStrategy"></property>
  </bean>
</beans>

Test.java


public class Test {
  public static void main(String[] params){
    //  Naming strategy 
    new Test().test();
    /*
      PhysicalNamingStrategy / catalog -> 
        null
      PhysicalNamingStrategy / catalog -> 
        null
      PhysicalNamingStrategy / column -> 
        DTYPE => dtype
      ImplicitNamingStrategy / PrimaryTableName -> 
        TestTable1Impl => TestTable1
      PhysicalNamingStrategy / table -> 
        TestTable1 => tb_test_table1
      ImplicitNamingStrategy / BasicColumnName -> 
        testId
      PhysicalNamingStrategy / column -> 
        testId => test_id
      ImplicitNamingStrategy / BasicColumnName -> 
        testId
      ImplicitNamingStrategy / BasicColumnName -> 
        testForeign
      PhysicalNamingStrategy / column -> 
        testForeign => test_foreign
      ImplicitNamingStrategy / BasicColumnName -> 
        testName
      PhysicalNamingStrategy / column -> 
        testName => test_name
      ImplicitNamingStrategy / BasicColumnName -> 
        testName
      PhysicalNamingStrategy / column -> 
        DTYPE => dtype
      PhysicalNamingStrategy / table -> 
        TestTable2Impl => tb_test_table2_impl
      ImplicitNamingStrategy / BasicColumnName -> 
        testId
      PhysicalNamingStrategy / column -> 
        testId => test_id
      ImplicitNamingStrategy / BasicColumnName -> 
        testId
      ImplicitNamingStrategy / BasicColumnName -> 
        testName
      PhysicalNamingStrategy / column -> 
        testName => test_name
      ImplicitNamingStrategy / BasicColumnName -> 
        testName
      ImplicitNamingStrategy / JoinColumnName -> 
        testForeign_testId => testForeign
      PhysicalNamingStrategy / column -> 
        testForeign => test_foreign
      ImplicitNamingStrategy / ForeignKeyName -> 
        FKlnurug7wfle1u6fc5oulnrx94 => fk_test_table1_test_foreign
      Hibernate: 
        alter table tb_test_table1 
          drop 
          foreign key fk_test_table1_test_foreign
      Hibernate: 
        drop table if exists tb_test_table1
      Hibernate: 
        drop table if exists tb_test_table2_impl
      Hibernate: 
        create table tb_test_table1 (
          test_id bigint not null auto_increment,
          test_name varchar(20),
          test_foreign bigint,
          primary key (test_id)
        )
      Hibernate: 
        create table tb_test_table2_impl (
          test_id bigint not null auto_increment,
          test_name varchar(20),
          primary key (test_id)
        )
      Hibernate: 
        alter table tb_test_table1 
          add constraint fk_test_table1_test_foreign 
          foreign key (test_foreign) 
          references tb_test_table2_impl (test_id)
      Hibernate: 
        alter table tb_test_table1 
          drop 
          foreign key fk_test_table1_test_foreign
      Hibernate: 
        drop table if exists tb_test_table1
      Hibernate: 
        drop table if exists tb_test_table2_impl
     */
  }
  public void test(){
    ApplicationContext context = new ClassPathXmlApplicationContext("spring.xml", this.getClass());
    SessionFactory factory = null;
    try {
      factory = (SessionFactory) context.getBean("sessionFactory");
    } finally {
      if(factory != null){
        factory.close();
        factory = null;
      }
    }
  }
}

Related articles: