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

Hibernate Envers查询_MOD列时列名不匹配问题求助

Hibernate Envers @Audited(withModifiedFlag=true) 列名不匹配问题的批量解决方案

我之前也遇到过类似的问题,结合你的场景(PostgreSQL + Hibernate 5.2.13 + Spring JPA默认命名策略),核心问题是Envers生成的_MOD列名和Spring命名策略转换后的查询列名不匹配,下面给你详细分析和批量解决办法:

问题复现

你的实体定义和生成的表结构完全对应了这个问题:

  • 实体属性fileName通过Spring命名策略转换为数据库列file_name
  • Envers生成的审计表中,modified列是fileName_MOD(基于属性名直接加后缀)
  • 但查询时Envers会用转换后的列名加_mod,即file_name_mod,导致PostgreSQL报错找不到列

根本原因

Spring的SpringPhysicalNamingStrategy会把Java驼峰命名转成数据库下划线小写格式,但Envers默认的DefaultModifiedColumnNamingStrategy是直接在实体属性名后拼接_MOD,而不是基于转换后的数据库列名生成modified列。这就造成了生成的列名和查询时期望的列名不一致。

批量解决方案

这里提供两种可靠的批量解决方式,你可以根据项目情况选择:

方式一:自定义Envers Modified列命名策略

通过实现Envers的ModifiedColumnNamingStrategy接口,让modified列名遵循Spring的命名规则:

  1. 实现自定义策略类
import org.hibernate.envers.configuration.ModifiedColumnNamingStrategy;
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class SpringEnversModifiedColumnNamingStrategy implements ModifiedColumnNamingStrategy {

    private final SpringPhysicalNamingStrategy physicalNamingStrategy = new SpringPhysicalNamingStrategy();

    @Override
    public String getModifiedColumnName(String originalColumnName) {
        // 先让Spring策略处理原列名,再添加_mod后缀
        Identifier originalId = Identifier.toIdentifier(originalColumnName);
        Identifier transformedId = physicalNamingStrategy.toPhysicalColumnName(originalId, null);
        return transformedId.getText() + "_mod";
    }
}
  1. 配置Hibernate使用该策略
    在application.properties中添加:
hibernate.envers.modified_column_naming_strategy=com.yourpackage.SpringEnversModifiedColumnNamingStrategy

(替换com.yourpackage为你的实际包路径)

方式二:扩展Spring物理命名策略处理Envers列

如果方式一不生效,可以扩展SpringPhysicalNamingStrategy,让它自动修正Envers生成的_MOD列名:

  1. 扩展命名策略类
import org.springframework.boot.orm.jpa.hibernate.SpringPhysicalNamingStrategy;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;

public class EnversAwareSpringPhysicalNamingStrategy extends SpringPhysicalNamingStrategy {

    @Override
    public Identifier toPhysicalColumnName(Identifier name, JdbcEnvironment context) {
        String columnName = name.getText();
        // 识别Envers的modified列(以_MOD结尾)
        if (columnName.endsWith("_MOD")) {
            // 去掉_MOD后缀,用Spring策略转换基础名,再加_mod
            String baseName = columnName.substring(0, columnName.length() - 4);
            Identifier baseId = Identifier.toIdentifier(baseName);
            Identifier transformedBase = super.toPhysicalColumnName(baseId, context);
            return Identifier.toIdentifier(transformedBase.getText() + "_mod");
        }
        return super.toPhysicalColumnName(name, context);
    }
}
  1. 替换默认的物理命名策略
    在application.properties中修改:
hibernate.physical_naming_strategy=com.yourpackage.EnversAwareSpringPhysicalNamingStrategy

临时方案(仅适用于少量实体)

如果只是个别实体需要审计,你可以手动指定modifiedColumnName:

@Column(name = "file_name")
@Audited(withModifiedFlag = true, modifiedColumnName = "file_name_mod")
private String fileName;

但显然这种方式在大量实体场景下不高效,还是推荐上面的批量解决方案。

内容的提问来源于stack exchange,提问作者andkov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 08:45:00