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

Spring Boot查询Oracle含UTF-8字符数据的编码问题求助

解决Spring Boot中Oracle Unicode字符过滤查询问题

核心问题

Oracle数据库本身不支持UTF-8编码,但部分表列通过N'...'字面量插入了Unicode字符,Spring Boot查询时这些字符被识别为?,无法正常过滤。


可行解决方案

方案1:调整JDBC连接参数(最简便)

Oracle JDBC驱动有专门的Unicode参数,替换你原有的连接配置:

spring.datasource.url=jdbc:oracle:thin:@111.11.1.111:1111:DB?oracle.jdbc.defaultNChar=true&oracle.jdbc.convertNcharStrings=true
server.servlet.encoding.charset=UTF-8
server.servlet.encoding.enabled=true
server.servlet.encoding.force=true
  • oracle.jdbc.defaultNChar=true:让JDBC默认以NCHAR类型发送字符串参数,等效于SQL中的N前缀
  • oracle.jdbc.convertNcharStrings=true:自动将字符串转换为Unicode编码

修改后原生查询无需额外处理,直接使用参数绑定即可:

@Query(value = "SELECT * FROM entity WHERE text LIKE CONCAT('%', :filter, '%') ORDER BY modified_date", nativeQuery = true)
Page<Entity> findAllByOrderByModifiedDateDesc(@Nullable @Param("filter") String filter, Pageable pageable);

方案2:HQL中使用Oracle函数转换

在HQL里通过TO_NCHAR函数将参数转换为Unicode类型,匹配存储的N'...'字符:

@Query("SELECT e FROM Entity e WHERE " +
       "(:filter is null or :filter = '' or " +
       "LOWER(e.text) LIKE CONCAT('%', LOWER(TO_NCHAR(:filter)), '%')) " +
       "ORDER BY e.modifiedDate DESC")
Page<Entity> findAllByOrderByModifiedDateDesc(@Nullable @Param("filter") String filter, Pageable pageable);

方案3:手动指定参数类型(原生查询兜底)

如果上述方案无效,可通过EntityManager手动指定参数为NVARCHAR类型:

@Repository
public class EntityRepositoryImpl implements EntityCustomRepository {

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Page<Entity> findAllWithUnicodeFilter(String filter, Pageable pageable) {
        if (filter == null || filter.isEmpty()) {
            // 无过滤条件时的查询逻辑
            TypedQuery<Entity> query = entityManager.createQuery(
                "SELECT e FROM Entity e ORDER BY e.modifiedDate DESC", Entity.class);
            query.setFirstResult((int) pageable.getOffset());
            query.setMaxResults(pageable.getPageSize());
            List<Entity> content = query.getResultList();
            long total = entityManager.createQuery(
                "SELECT COUNT(e) FROM Entity e", Long.class).getSingleResult();
            return new PageImpl<>(content, pageable, total);
        }

        // 带Unicode过滤的原生查询
        String sql = "SELECT * FROM entity WHERE text LIKE CONCAT('%', :filter, '%') ORDER BY modified_date";
        Query nativeQuery = entityManager.createNativeQuery(sql, Entity.class);
        nativeQuery.setParameter("filter", filter, Types.NVARCHAR);
        nativeQuery.setFirstResult((int) pageable.getOffset());
        nativeQuery.setMaxResults(pageable.getPageSize());
        List<Entity> content = nativeQuery.getResultList();

        // 统计总数
        String countSql = "SELECT COUNT(*) FROM entity WHERE text LIKE CONCAT('%', :filter, '%')";
        Query countQuery = entityManager.createNativeQuery(countSql);
        countQuery.setParameter("filter", filter, Types.NVARCHAR);
        long total = ((Number) countQuery.getSingleResult()).longValue();

        return new PageImpl<>(content, pageable, total);
    }
}

需先定义自定义接口EntityCustomRepository,让你的JpaRepository继承该接口。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 08:07:19