如何使用Hibernate 6创建自定义强制转换间隔postgres sql函数

bxpogfeg  于 2023-02-09  发布在  其他
关注(0)|答案(1)|浏览(189)

我有一个定制的sql方言,用来创建一个timebucket函数和一个cast interval函数,但在迁移到springboot 3.0后就不再工作了。我一直在努力迁移这个,但遇到了一个障碍,因为“SQLFunction”已经不存在了。请在下面找到我的旧代码:

import org.hibernate.QueryException
import org.hibernate.dialect.PostgreSQL10Dialect
import org.hibernate.dialect.function.SQLFunction
import org.hibernate.dialect.function.StandardSQLFunction
import org.hibernate.engine.spi.Mapping
import org.hibernate.engine.spi.SessionFactoryImplementor
import org.hibernate.type.OffsetDateTimeType
import org.hibernate.type.Type

class CustomPostgresqlDialect : PostgreSQL10Dialect() {
  init {
    class CastInterval : SQLFunction {
      override fun hasArguments(): Boolean {
        return true
      }

      override fun hasParenthesesIfNoArguments(): Boolean {
        return true
      }

      @Throws(QueryException::class)
      override fun getReturnType(firstArgumentType: Type?, mapping: Mapping?): Type? {
        return firstArgumentType
      }

      @Throws(QueryException::class)
      override fun render(
        firstArgumentType: Type?,
        args: List<*>,
        factory: SessionFactoryImplementor?
      ): String {
        return "cast(" + args[0] + " as interval)"
      }
    }
    this.registerFunction(
      "time_bucket",
      StandardSQLFunction("time_bucket", OffsetDateTimeType())
    )
    this.registerFunction("castInterval", CastInterval())
  }
}

现在我决定使用MetadatabuilderContributor,而不是再次使用自定义方言,并且迁移time_bucket函数很容易,但是重新创建CastInterval函数被证明是更困难的。我阅读到SqmFunctionDescriptor将被用作SQLFunction的替代品,但是我对hib的内部工作方式不是很熟悉。目前为止我所拥有的代码如下:

class CustomMetadataBuilderContributor : MetadataBuilderContributor {

  override fun contribute(metadataBuilder: MetadataBuilder) {
    metadataBuilder.applySqlFunction(
      "time_bucket", StandardSQLFunction("time_bucket", StandardBasicTypes.OFFSET_DATE_TIME)
    )
    metadataBuilder.applySqlFunction("castInterval", CastInterval())
  }
}

任何关于如何执行这一点的投入都将是有益的。

rqenqsqc

rqenqsqc1#

首先,你应该使用FunctionContributor契约,实现起来相当简单,你只需要注册一个函数模式:

class CustomMetadataBuilderContributor : FunctionContributor {

  override fun contributeFunctions(functionContributions: FunctionContributions) {
    functionContributions.getFunctionRegistry().registerNamed(
      "time_bucket", StandardBasicTypes.OFFSET_DATE_TIME
    )
    functionContributions.getFunctionRegistry().registerPattern(
      "castInterval", "cast(?1 as interval)"
    )
  }
}

相关问题