SpringBoot JPA Oracle原生查询含CURSOR报JDBC类型-10无方言映射错误
问题根因
JDBC类型码-10对应java.sql.Types.REF_CURSOR,即SQL中CURSOR()表达式返回的游标类型。默认的Oracle12cDialect未注册该JDBC类型到Hibernate类型的映射规则,Hibernate无法处理该列的类型转换,因此抛出No Dialect mapping for JDBC type: -10异常。
解决方案
该方案不需要修改原有SQL语句,仅需3步配置即可:
1. 自定义Oracle方言补全类型映射
新建自定义方言类,继承官方Oracle12cDialect,在构造方法中注册缺失的REF_CURSOR映射:
import org.hibernate.dialect.Oracle12cDialect; import org.hibernate.type.StandardBasicTypes; import java.sql.Types; public class CustomOracle12cDialect extends Oracle12cDialect { public CustomOracle12cDialect() { super(); registerHibernateType(Types.REF_CURSOR, StandardBasicTypes.CURSOR.getName()); } }
2. 更新JPA方言配置
在Spring Boot配置文件中,将原有JPA方言配置替换为自定义方言的全限定类名:
spring: jpa: properties: hibernate: dialect: com.yourownpackage.CustomOracle12cDialect # 替换为类的实际存放路径
如果是properties格式配置,添加如下行:
spring.jpa.properties.hibernate.dialect=com.yourownpackage.CustomOracle12cDialect
3. 调整查询结果接收逻辑
CURSOR列返回的是JDBCResultSet实例,Spring Data JPA无法自动将其映射为普通POJO、实体类或接口投影,需要将Repository查询方法的返回值定义为List<Object[]>,数组顺序与SELECT语句的列顺序完全对应:
- 普通列(a/b/c等)会按默认规则映射为对应的Java基础类型(字符串、数字、时间等)
- CURSOR表达式对应的位置返回
java.sql.ResultSet实例,可手动遍历获取子查询返回的所有数据 - 必须手动关闭遍历完成的ResultSet,推荐使用try-with-resources语法处理,避免数据库游标泄漏。
Repository示例代码:
public interface TestRepository extends JpaRepository<TestEntity, Long> { @Query(value = "SELECT a, b, c, CURSOR( SELECT ... FROM ... ), ... FROM ... WHERE ...", nativeQuery = true) List<Object[]> runOriginalQuery(); }
业务层调用示例:
List<Object[]> resultRows = testRepository.runOriginalQuery(); for (Object[] row : resultRows) { // 按列顺序读取普通字段 String fieldA = (String) row[0]; Long fieldB = (Long) row[1]; LocalDateTime fieldC = (LocalDateTime) row[2]; // 处理游标列 try (ResultSet subCursor = (ResultSet) row[3]) { while (subCursor.next()) { // 按子查询的列顺序读取字段,做业务处理 // String subField1 = subCursor.getString(1); } } catch (SQLException e) { // 按需处理SQL异常 } // 处理其余后续列 }
内容的提问来源于stack exchange,提问作者Casti
相关产品推荐
相关产品推荐

