Hibernate 6.2构建命名策略为列加表名前缀:如何获取表名?
问题:Hibernate 6.2.x 中如何在
determineBasicColumnName方法内获取表名 我希望数据库中所有基础列和主键都以表名为前缀,例如Person实体的name和age属性对应生成的表结构如下:
CREATE TABLE person ( person_id, person_name text, person_age int)
这样便于在PostgreSQL中使用自然连接。
在Hibernate 6.1.7(对应Spring Boot 3.0.5)中,我使用以下命名策略可以实现需求:
import org.hibernate.boot.model.naming.*; import org.hibernate.cfg.AnnotatedColumn; import java.lang.reflect.Field; public class HibernateImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl { @Override public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) { String name = source.getReferencedColumnName().toString().toLowerCase(); return toIdentifier(name, source.getBuildingContext()); } @Override public Identifier determinePrimaryTableName(ImplicitEntityNameSource source) { return super.determinePrimaryTableName(source); } @Override public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) { try { Field field = source.getClass().getDeclaredField("this$0"); field.setAccessible(true); AnnotatedColumn column = (AnnotatedColumn) field.get(source); // explicit naming oder implicit String tableName = column.getTable().getName().toLowerCase(); final Identifier basicColumnName = super.determineBasicColumnName(source); String columnName = tableName + "_" + basicColumnName.toString().toLowerCase(); return Identifier.toIdentifier(columnName); } catch (Exception e) { return super.determineBasicColumnName(source); } } }
但升级到Hibernate 6.2.x(对应Spring Boot 3.1.x)后该策略失效:
AnnotatedColumn类已迁移到新包:import org.hibernate.boot.model.internal.AnnotatedColumn;- 新的
AnnotatedColumn没有getTable()方法。
我知道可能需要改用更通用的命名策略,但当前想了解:是否有方法在determineBasicColumnName方法内获取表名?
解决方案
在Hibernate 6.2+中,无需依赖反射或内部私有类,可通过ImplicitBasicColumnNameSource提供的合法API获取表名:
import org.hibernate.boot.model.naming.*; public class HibernateImplicitNamingStrategy extends ImplicitNamingStrategyComponentPathImpl { @Override public Identifier determineJoinColumnName(ImplicitJoinColumnNameSource source) { String name = source.getReferencedColumnName().toString().toLowerCase(); return toIdentifier(name, source.getBuildingContext()); } @Override public Identifier determineBasicColumnName(ImplicitBasicColumnNameSource source) { // 从属性路径中提取表名 String tableName = source.getPath().getParent().getLocalName().toLowerCase(); Identifier basicColumnName = super.determineBasicColumnName(source); String columnName = tableName + "_" + basicColumnName.toString().toLowerCase(); return Identifier.toIdentifier(columnName); } }
说明
source.getPath()返回AttributePath对象,调用getParent()可拿到对应实体的路径节点,其getLocalName()即为当前字段所属表的名称(已按Hibernate默认命名规则处理)。- 这种方式不依赖内部实现细节,是官方支持的合法用法,兼容性和稳定性更好。
- 若处理嵌套嵌入式组件的字段,可根据路径层级调整解析逻辑,普通实体的基础字段直接用上述代码即可生效。
内容的提问来源于stack exchange,提问作者Janning Vygen
相关产品推荐
相关产品推荐

