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

Spring Boot 2转3(Hibernate5升6):registerFunction被移除的适配问题

Spring Boot 3(Hibernate 6)适配自定义SQL函数替代registerFunction方案

在Hibernate 6中,原Dialect类的registerFunction方法已被移除,替代方案是通过重写initializeFunctionRegistry方法或直接操作FunctionRegistry来注册自定义SQL函数。以下是针对你的ExtendSqlServer2012Dialect的具体适配方案:

方案1:重写Dialect的initializeFunctionRegistry方法

这是最直接的替代方式,延续原有自定义Dialect的思路:

public class ExtendSqlServer2012Dialect extends SqlServer2012Dialect {
    @Override
    protected void initializeFunctionRegistry(FunctionRegistry registry) {
        // 先调用父类方法初始化默认函数
        super.initializeFunctionRegistry(registry);
        
        // 注册datediffhr:映射到SQL的datediff(hour, 参数1, 参数2)
        registry.registerPattern(
            "datediffhr", 
            "datediff(hour, ?1, ?2)", 
            StandardBasicTypes.INTEGER
        );
        
        // 注册dateaddhr:映射到SQL的dateadd(hour, 参数1, 参数2)
        registry.registerPattern(
            "dateaddhr", 
            "dateadd(hour, ?1, ?2)", 
            StandardBasicTypes.TIMESTAMP
        );
    }
}

复杂场景扩展

如果需要自定义参数校验、类型转换等逻辑,可以直接实现SqlFunction接口注册:

registry.registerFunction("datediffhr", new SqlFunction() {
    @Override
    public ReturnType resolveReturnType(Type argumentType, Mapping mapping) {
        return StandardBasicTypes.INTEGER.getReturnedClass();
    }

    @Override
    public boolean hasArguments() {
        return true;
    }

    @Override
    public boolean hasParenthesesIfNoArguments() {
        return true;
    }

    @Override
    public String render(Type argumentType, List<?> arguments, SessionFactoryImplementor sessionFactory) {
        if (arguments.size() != 2) {
            throw new IllegalArgumentException("datediffhr requires exactly 2 arguments");
        }
        return String.format("datediff(hour, %s, %s)", arguments.get(0), arguments.get(1));
    }
});

方案2:不自定义Dialect,通过MetadataBuilder注册函数

如果不想维护自定义Dialect,可以在Spring Boot配置类中直接注册函数:

@Configuration
public class HibernateFunctionConfig {
    @Bean
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(DataSource dataSource) {
        LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
        em.setDataSource(dataSource);
        em.setPackagesToScan("com.yourproject.entity");
        
        HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
        em.setJpaVendorAdapter(vendorAdapter);
        
        Properties jpaProps = new Properties();
        jpaProps.setProperty("hibernate.dialect", "org.hibernate.dialect.SQLServer2012Dialect");
        em.setJpaProperties(jpaProps);
        
        // 注册自定义SQL函数
        em.setEntityManagerFactoryCallbacks(new EntityManagerFactoryCallback() {
            @Override
            public void postProcessEntityManagerFactory(EntityManagerFactory emf) {
                SessionFactory sessionFactory = emf.unwrap(SessionFactory.class);
                MetadataImplementor metadata = (MetadataImplementor) sessionFactory.getMetadata();
                FunctionRegistry registry = metadata.getSqlFunctionRegistry();
                
                registry.registerPattern("datediffhr", "datediff(hour, ?1, ?2)", StandardBasicTypes.INTEGER);
                registry.registerPattern("dateaddhr", "dateadd(hour, ?1, ?2)", StandardBasicTypes.TIMESTAMP);
            }
        });
        
        return em;
    }
}

配置注意事项

  • 若使用方案1,需在Spring Boot配置文件中指定自定义Dialect:
    spring.jpa.properties.hibernate.dialect=com.yourproject.ExtendSqlServer2012Dialect
    
  • registerPattern方法中的?1、?2对应函数调用时的参数顺序,无需手动拼接参数,Hibernate会自动处理参数绑定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 16:45:14