我想使用来自hibernate-types-52(@Vlad Mihalcea)的UUID和Range类型进行冬眠本机标量投影(使用Tuple.class)。
我正在使用:
我已经声明了自定义的PostgreSQL方言
class CustomPostgreSQLDialect : PostgreSQL10Dialect() {
init {
this.registerColumnType(Types.BLOB, "bytea");
this.registerHibernateType(Types.OTHER, PostgresUUIDType::class.java.name)
//this.registerHibernateType(Types.OTHER, PostgreSQLRangeType::class.java.name)
}
override fun remapSqlTypeDescriptor(sqlTypeDescriptor: SqlTypeDescriptor): SqlTypeDescriptor {
return if (sqlTypeDescriptor.sqlType == Types.BLOB) {
BinaryTypeDescriptor.INSTANCE
} else super.remapSqlTypeDescriptor(sqlTypeDescriptor)
}
}
当下一行是注释时
this.registerHibernateType(Types.OTHER, PostgreSQLRangeType::class.java.name)
[并且仅当我投射范围列时,它才能正常工作。
val statement = "SELECT uuidColumn, CAST(rangeColumn as TEXT) FROM ...."
entityManager.createNativeQuery(statement, Tuple::class.java)
如果我是对的,我只能为java.sql.Types.OTHER声明一个映射,如果我声明多个,则使用最后一个。确实,如果两者都不加注释,则我有一个ClassCastException,因为UUID无法转换为PGObject。
是否有一种方法可以使用UUID和Range类型进行本机标量投影(使用Tuple.class),而无需强制转换一个或另一个?最后,我想像下面这样写我的查询
val statement = "SELECT uuidColumn, rangeColumn FROM ...."
entityManager.createNativeQuery(statement, Tuple::class.java)
我知道以下选项
@SqlResultSetMapping(
name="ProjectioName",
columns=[
ColumnResult(name="uuidColumn", type = PostgresUUIDType::class),
ColumnResult(name="rangeColumn", type = PostgreSQLRangeType::class)
]
)
entityManager.createNativeQuery(statement, "ProjectioName")
问题是我不想为所有具有UUID和其他特定列(JSON,Range,...)的投影声明'SqlResultSetMapping'。
或
entityManager.createNativeQuery(statement, Tuple::class.java)
.unwrap(NativeQuery::class.java)
.addScalar("uuidColumn", PostgresUUIDType.INSTANCE)
.addScalar("rangeColumn", PostgreSQLRangeType.INSTANCE)
此选项可能很好,但是我有很多列,如果我开始添加“ .addScalar(...)”,则需要定义所有列。从概念上讲,我想对某些特定的列使用“ .addScalar(...)”,对于那些我未声明的列,则使用默认的“策略”,这可能吗?
这是一个非常常见的问题,所以此答案基于我之前写的this article。
JDBC Types
interface定义了所有常见的SQL列类型,例如Types
,VARCHAR
,INTEGER
。
但是,对于特定于数据库的列,只有DATE
条目可以引用它们。
因此,如果您的一个表同时定义了Types.OTHER
列和UUID列,那么,当您从该表中获取行时,这两个列都将使用Range
JDBC类型。
因此,您不能注册默认的休眠类型来覆盖Range
,因为根据数据库特定的列类型,您需要不同的类型。
您需要在查询级显式定义Hibernate Types.OTHER
:
Types.OTHER
现在,您的问题是:
此选项可能很好,但是如果我开始的话,我会有很多列添加了“ .addScalar(...)”,我需要定义所有列。
而且,有解决方案。
您可以使用Type
动态建立查询。基于List<Tuple> tuples = entityManager
.createNativeQuery(
"SELECT uuidColumn, CAST(rangeColumn as TEXT) " +
"FROM book ", Tuple.class)
.unwrap(org.hibernate.query.NativeQuery.class)
.addScalar("uuidColumn", PostgresUUIDType.INSTANCE)
.addScalar("rangeColumn", PostgreSQLRangeType.INSTANCE)
.getResultList();
,可以在构建投影查询时应用正确的Hibernate Criteria API。