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

Hibernate 6自定义用户类型JdbcType错误致查询函数执行异常

在Hibernate 6中使用自定义UserType调用upper等字符串函数时抛出类型不匹配异常

问题背景

使用Quarkus 3.1.2.Final(集成Hibernate Core 6.2.4.Final)开发项目,为自定义类MyStringWrapper实现了MyStringUserType自定义用户类型,实体中配置如下:

@Type(MyStringUserType.class)
public MyStringWrapper field;

当通过Criteria API执行包含upper这类字符串函数的查询时,触发类型不匹配异常,相同逻辑在Hibernate 5中可正常运行。

复现代码

查询方法:

@Transactional
List<MyEntity> getByQuery() {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<MyEntity> query = cb.createQuery(MyEntity.class);
    Root<MyEntity> root = query.from(MyEntity.class);

    query.where(
            cb.equal(cb.upper(root.get("field")), new MyStringWrapper("SOME VALUE"))
    );
    TypedQuery<MyEntity> result = em.createQuery(query);
    return result.getResultList();
}

异常信息

[ERROR] org.acme.UserTypeTest.testQuery  Time elapsed: 0.129 s  <<< ERROR!
org.hibernate.QueryException: Parameter 1 of function upper() has type
STRING, but argument is of type org.acme.MyStringWrapper
...

调试发现

org.hibernate.query.sqm.produce.function.ArgumentTypesValidator#getJdbcType方法返回VarbinaryJdbcType,导致校验时因非字符类型触发错误,但自定义用户类型的getSqlType明明返回java.sql.Types.VARCHAR,预期应使用VarcharJdbcType。尝试添加@JdbcType(VarcharJdbcType.class)和@JdbcTypeCode(Types.VARCHAR)注解未能解决问题。

解决方案

Hibernate 6对自定义用户类型的类型推导逻辑做了调整,要让字符串函数正确识别自定义类型,需按以下方式修改:

1. 让自定义UserType实现StringRepresentableJdbcType接口

显式告知Hibernate该类型属于字符串可表示类型,这样upper/substring等函数能正确识别其字符属性:

public class MyStringUserType implements UserType<MyStringWrapper>, StringRepresentableJdbcType<MyStringWrapper> {
    // 原有UserType的实现逻辑(比如nullSafeGet、nullSafeSet等)

    @Override
    public String toString(MyStringWrapper value) {
        return value != null ? value.getValue() : null;
    }

    @Override
    public MyStringWrapper fromString(CharSequence string) {
        return string != null ? new MyStringWrapper(string.toString()) : null;
    }
}

2. 补充字段注解

在实体字段上明确指定JDBC类型代码:

@Type(MyStringUserType.class)
@JdbcTypeCode(Types.VARCHAR)
public MyStringWrapper field;

3. 备选方案:改用CompositeUserType

如果自定义类型需要更复杂的映射逻辑,Hibernate 6推荐使用CompositeUserType,它在类型推导和函数支持上有更好的兼容性。

经过上述调整后,Hibernate能正确识别自定义类型对应的JDBC类型为VARCHAR,upper等字符串函数即可正常处理该字段。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 23:02:50