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

Spring Boot3迁移后Hibernate6.3中@Lob字段调用lower()抛异常

Spring Boot 3 + Hibernate 6.3 中@Lob字段Criteria查询lower()函数报错解决方法

问题场景

将项目从Spring Boot 2迁移至Spring Boot 3(搭配Hibernate 6.3.1 Final、Java 17)后,使用Criteria查询带@Lob注解的String类型字段时,抛出InvalidDataAccessResourceUsageException异常,异常信息如下:

jakarta.servlet.ServletException: Request processing failed: org.springframework.dao.InvalidDataAccessResourceUsageException: Parameter 1 of function 'lower()' has type 'STRING', but argument is of type 'java.lang.String'

相关实体类与查询代码如下:

实体类

@Entity
public class FooEntity {
    @Id
    private Long id;

    @Column
    @Lob
    private String comment;

    // 其他字段与方法
}

查询代码

public List<FooEntity> search(FooFilters filters) {
    Specification<FooEntity> specification = getSpecification(filters);
    return fooRepository.findAll(specification);
}

private Specification<FooEntity> getSpecification(FooFilters filters) {
    return (root, query, criteriaBuilder) -> {
        List<Predicate> p = new ArrayList<>();

        if (StringUtils.isNotBlank(filters.comment())) {
            p.add(criteriaBuilder.like(
                    criteriaBuilder.lower(root.get(FooEntity_.COMMENT)),
                    "%" + filters.comment() + "%"));
        }

        return criteriaBuilder.and(p.toArray(Predicate[]::new));
    };
}

移除@Lob注解后查询可正常执行,测试基于H2数据库。

原因分析

Hibernate 6对@Lob类型的映射逻辑与旧版本不同:标注@Lob的String字段在H2数据库中会被映射为CLOB类型,而criteriaBuilder.lower()默认期望处理的是标准STRING类型,导致类型不匹配报错。

解决方案

方案1:显式转换字段类型后调用lower()

在Criteria查询中,先将CLOB类型的字段显式转换为String类型,再执行lower()操作:

private Specification<FooEntity> getSpecification(FooFilters filters) {
    return (root, query, criteriaBuilder) -> {
        List<Predicate> p = new ArrayList<>();

        if (StringUtils.isNotBlank(filters.comment())) {
            // 显式转换CLOB为String类型
            Expression<String> commentExpr = criteriaBuilder.cast(root.get(FooEntity_.COMMENT), String.class);
            p.add(criteriaBuilder.like(
                    criteriaBuilder.lower(commentExpr),
                    "%" + filters.comment().toLowerCase() + "%"));
        }

        return criteriaBuilder.and(p.toArray(Predicate[]::new));
    };
}

方案2:修改实体字段的映射类型

如果字段长度允许,可通过@Column的columnDefinition指定字段为VARCHAR类型,同时保留@Lob以支持大文本存储(适用于H2等支持大VARCHAR的数据库):

@Entity
public class FooEntity {
    @Id
    private Long id;

    @Column(columnDefinition = "VARCHAR(2000)") // 根据实际需求调整长度
    @Lob
    private String comment;

    // 其他字段与方法
}

方案3:直接调用数据库原生LOWER函数

通过criteriaBuilder.function()调用H2数据库的原生LOWER函数,直接处理CLOB类型:

private Specification<FooEntity> getSpecification(FooFilters filters) {
    return (root, query, criteriaBuilder) -> {
        List<Predicate> p = new ArrayList<>();

        if (StringUtils.isNotBlank(filters.comment())) {
            Expression<String> lowerComment = criteriaBuilder.function(
                    "LOWER",
                    String.class,
                    root.get(FooEntity_.COMMENT)
            );
            p.add(criteriaBuilder.like(lowerComment, "%" + filters.comment().toLowerCase() + "%"));
        }

        return criteriaBuilder.and(p.toArray(Predicate[]::new));
    };
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 16:56:10