Hibernate命名策略
hibernate的命名策略,可以减少对数据库标识符命名的维护,进一步减少这部份命名的重复性代码量,以提高维护。
hibernate的命名方式,有两类,一类是显式命名,一类是隐式命名。
- 显式命名:在映射配置时,设置的数据库表名,列名等,就是进行显式命名。
- 隐式命名:显式命名一般不是必要的,所以可以选择当不设置名称,这时就交由hibernate进行隐式命名,另外隐式命名还包括那些不能进行显式命名的数据库标识符。接口ImplicitNamingStrategy,就是用于实现隐式命名。
- 过滤命名:接口PhysicalNamingStrategy,用于对显式命名或隐式命名进一步过滤处理。
示例:
TestTable1Impl.java
@Entity // 隐式命名表名 @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 // 显式命名表名 @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"> <!-- 配置数据源 --> <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> <!-- 可以加多个包 --> <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){ // 命名策略 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; } } } }