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

Spring Data JPA Specification实现SQL Server高棉语LIKE查询(带N前缀)

问题描述

基于Spring Boot + Spring Data JPA + SQL Server 2017开发应用时,需要用LIKE表达式查询高棉语Unicode数据。在SQL Server Management Studio中执行以下语句可正常返回结果:

SELECT * FROM merchant_holiday_setting WHERE description_kh LIKE N'%ទិវា%'

但通过JPA Specification Criteria实现时无法正常匹配,当前的Kotlin代码如下:

override fun findAllList(q: String?, page: Int, size: Int): Page<MerchantHolidaySetting>? {
    return mchHolidayRepo.findAll({ root, cq, cb ->
        val predicate = ArrayList<Predicate>()
        q?.let {
            println("Query $q")
            val descEn = cb.like(cb.upper(root.get("description")), "%${q.toUpperCase()}%")
            val descKh = cb.like(root.get("descriptionKh"), "%$q%")
            predicate.add(cb.or(descEn, descKh))
        }
        predicate.add(cb.isTrue(root.get("status")))
        cq.orderBy(cb.asc(root.get<Date>("holidayDate")))
        cb.and(*predicate.toTypedArray())
    }, PageRequest.of(page, size))
}
解决方案

问题核心在于SQL Server中N'%xxx%'的N前缀表示该字符串为Unicode(NVARCHAR类型),而JPA默认生成的SQL不会自动添加这个前缀,导致高棉语字符无法被正确识别匹配。以下两种方法可以解决:

方法一:修改Hibernate配置(推荐)

通过配置让Hibernate默认将所有String参数按NVARCHAR类型处理,自动生成带N前缀的SQL。在application.properties或application.yml中添加以下配置:

# 指定SQL Server方言
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.SQLServer2012Dialect
# 让所有String参数默认使用NVARCHAR类型
spring.jpa.properties.hibernate.connection.defaultNChar=true

添加配置后,原有的JPA Specification代码无需修改即可正常匹配高棉语Unicode数据。

方法二:手动构造带N前缀的LIKE条件

如果不想修改全局配置,可以在Specification中手动构造带N前缀的匹配条件,同时保持参数绑定避免SQL注入:

override fun findAllList(q: String?, page: Int, size: Int): Page<MerchantHolidaySetting>? {
    return mchHolidayRepo.findAll({ root, cq, cb ->
        val predicate = ArrayList<Predicate>()
        q?.let {
            println("Query $q")
            val descEn = cb.like(cb.upper(root.get("description")), "%${q.toUpperCase()}%")
            // 手动构造带N前缀的Unicode匹配条件
            val khPattern = cb.concat(cb.literal("N'%"), cb.concat(q, cb.literal("%")))
            val descKh = cb.like(root.get("descriptionKh"), khPattern)
            predicate.add(cb.or(descEn, descKh))
        }
        predicate.add(cb.isTrue(root.get("status")))
        cq.orderBy(cb.asc(root.get<Date>("holidayDate")))
        cb.and(*predicate.toTypedArray())
    }, PageRequest.of(page, size))
}

这种方式会让JPA生成类似description_kh LIKE N'%?%'的SQL,确保高棉语字符被正确解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 17:09:47