Hibernate5 ImplicitNamingStrategy与PhysicalNamingStrategy

tech2026-03-27  0

Hibernate5中自定义实体类与数据库命名规则的方法相比之前版本有较大改变,在hibernate5之前的版本实现NamingStrategy就可以实现自定义规则,hibernate5改为通过ImplicitNamingStrategy与PhysicalNamingStrategy实现。

关于ImplicitNamingStrategy与PhysicalNamingStrategy详细的解释可以看官方文档,也可以参考其它博文,这里不在详述,参考博文:Hibernate入门之命名策略(naming strategy)详解

简单介绍一下ImplicitNamingStrategy与PhysicalNamingStrategy

ImplicitNamingStrategy:隐式规则,如果实体类没有@Entity(name = "table_xxx")或@Column(name="column_xxx")等指定数据库表名或列名的话,ImplicitNamingStrategy有效,如果在注解中指定名称,则以注解为准。

PhysicalNamingStrategy:物理规则,不管有没有@Entity(name = "table_xxx")或@Column(name="column_xxx")等注解命名,都要按自定义的PhysicalNamingStrategy规则映射数据库名称。

下面用示例来说明实际使用方法

需求一:为了统一命名规范,强制要求数据库映射实体类属性字段使用驼峰命名,数据库字段使用下划线_命名,而又不想麻烦在实体类每个属性上都加上@Column(name="column_xxx")注解,而是没有注解的根据属性名自动映射数据库字段,有注解的则使用注解的名称映射,那么应该使用ImplicitNamingStrategy。

hibernate已经提供了多个ImplicitNamingStrategy的实现,我们基于其中一个实现ImplicitNamingStrategyJpaCompliantImpl来做扩展

public class MyImplicitNamingStrategy extends ImplicitNamingStrategyJpaCompliantImpl { private static final long serialVersionUID = 1l; @Override public Identifier determineJoinTableName(ImplicitJoinTableNameSource source) { String name = source.getOwningPhysicalTableName() + "_" + source.getAssociationOwningAttributePath().getProperty(); return toIdentifier(name, source.getBuildingContext()); } /** * 重写此方法实现,驼峰转_ */ @Override public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) { String name = transformAttributePath( source.getAttributePath() ); name = addUnderscores(name); return toIdentifier( name, source.getBuildingContext() ); } protected static String addUnderscores(String name) { StringBuilder buf = new StringBuilder( name.replace('.', '_') ); for (int i=1; i<buf.length()-1; i++) { if ( Character.isLowerCase( buf.charAt(i-1) ) && Character.isUpperCase( buf.charAt(i) ) && Character.isLowerCase( buf.charAt(i+1) ) ) { buf.insert(i++, '_'); } } return buf.toString().toLowerCase(Locale.ROOT); } }

只需要重写determineBasicColumnName(ImplicitBasicColumnNameSource source)方法即可实现改变列名命名规则

 

需求二:统一管理数据库表的前缀与后缀,如果在每个@Entity(name = "table_xxx")中都加上前后缀,会比较麻烦切不便于统一管理,那么可以通过自定义PhysicalNamingStrategy实现

hibernate依然提供了多个PhysicalNamingStrategy的实现,我们基于其中的PhysicalNamingStrategyStandardImpl来实现需求

public class MyPhysicalNamingStrategy extends PhysicalNamingStrategyStandardImpl { private static final long serialVersionUID = 1l; /** * 数据库表前缀 */ private String prefix; /** * 数据库表后缀 */ private String suffix; /** * 数据库表前缀 */ public String getPrefix() { return prefix; } /** * 数据库表前缀 */ public void setPrefix(String prefix) { this.prefix = prefix; } /** * 数据库表后缀 */ public String getSuffix() { return suffix; } /** * 数据库表后缀 */ public void setSuffix(String suffix) { this.suffix = suffix; } /** * 重写方法实现自动追加前缀后缀 */ @Override public Identifier toPhysicalTableName(Identifier name, JdbcEnvironment context) { StringBuilder nameSB = new StringBuilder(); if(!StringUtils.isEmpty(prefix)) { nameSB.append(prefix); } nameSB.append(name.getText()); if(!StringUtils.isEmpty(suffix)) { nameSB.append(suffix); } return new Identifier(nameSB.toString(), name.isQuoted()); } }

重写toPhysicalTableName方法即可实现对表名的规则定制

 

使用方法

<bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean"> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="hibernate.default_batch_fetch_size">16</prop> </props> </property> <property name="implicitNamingStrategy" ref="myImplicitNamingStrategy" /> <property name="physicalNamingStrategy" ref="myPhysicalNamingStrategy" /> </bean> <!-- 这里是自定义的两个类的bean --> <bean id="myImplicitNamingStrategy" class="com.test.MyImplicitNamingStrategy"/> <bean id="myPhysicalNamingStrategy" class="com.test.MyPhysicalNamingStrategy"> <property name="prefix" value="u_"/> <property name="suffix" value="_s"/> </bean>

 

最新回复(0)