You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 20:22:11