Hibernate 6.x.x Oracle原生查询SUM计算字段丢失小数问题求助
解决方案
方案1:修改Oracle JDBC连接参数
在JDBC URL中添加oracle.jdbc.mapNumericToInt=false,禁用驱动自动将可转换为整数的数值类型映射为Java Integer类型。这是最便捷的方案,无需修改代码或SQL:
spring.datasource.url=jdbc:oracle:thin:@//your-oracle-host:1521/your-service?oracle.jdbc.mapNumericToInt=false
原理:Oracle JDBC驱动默认会把诸如39.74这类可被截断为整数的数值自动转成Integer,导致小数部分丢失。关闭该参数后,驱动会保留原始数值精度,返回BigDecimal类型。
方案2:自定义Hibernate类型贡献者
创建自定义类型处理SUM函数的返回值,强制映射为高精度数值类型:
- 编写类型贡献者类:
package com.yourpackage; import org.hibernate.boot.model.TypeContributions; import org.hibernate.boot.model.TypeContributor; import org.hibernate.service.ServiceRegistry; import org.hibernate.type.descriptor.sql.DecimalTypeDescriptor; public class OracleSumTypeContributor implements TypeContributor { @Override public void contribute(TypeContributions typeContributions, ServiceRegistry serviceRegistry) { // 注册针对SUM结果的自定义类型映射,强制使用NUMERIC类型 typeContributions.contributeSqlTypeDescriptorOverride( new DecimalTypeDescriptor() { @Override public int getSqlType() { return java.sql.Types.NUMERIC; } } ); } }
- 在Spring Boot配置中指定类型贡献者:
spring.jpa.properties.hibernate.type_contributors=com.yourpackage.OracleSumTypeContributor
原理:通过自定义SQL类型描述符,让Hibernate将SUM函数的结果识别为高精度的NUMERIC类型,避免被截断为整数。
方案3:使用TupleTransformer手动转换结果
在执行原生查询时,通过TupleTransformer手动转换返回值类型,修复被截断的数值:
import org.hibernate.query.TupleTransformer; import jakarta.persistence.EntityManager; import java.math.BigDecimal; import java.math.RoundingMode; // 业务代码中执行查询 EntityManager entityManager = ...; // 注入或获取EntityManager BigDecimal result = (BigDecimal) entityManager.createNativeQuery("SELECT SUM(39.74) AS total FROM dual") .setTupleTransformer(new TupleTransformer<Object>() { @Override public Object transformTuple(Object[] tuple, String[] aliases) { if (tuple[0] instanceof Integer) { // 将截断的整数转换为带两位小数的BigDecimal return BigDecimal.valueOf((Integer) tuple[0]).divide(BigDecimal.ONE, 2, RoundingMode.HALF_UP); } return tuple[0]; } }) .getSingleResult();
原理:Hibernate 6推荐使用TupleTransformer替代旧的ResultTransformer,通过手动检查结果类型并转换,恢复丢失的小数部分。
内容的提问来源于stack exchange,提问作者Isaachjk
相关产品推荐
相关产品推荐

