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

Spring Boot 3升级后使用SUM SQL函数触发ConverterNotFoundException求助

解决Spring Boot 3中SUM聚合函数返回值转自定义Price类型的ConverterNotFoundException问题

问题原因

你的PriceConverter是JPA的AttributeConverter,它仅负责实体属性与数据库列之间的双向转换。但当使用SUM(x.price)这类聚合函数时,查询返回的是原生BigDecimal值(被Spring Data JPA包装为TupleBackedMap),此时JPA属性转换器不会触发,Spring Data找不到对应类型的转换逻辑,因此抛出该异常。

解决方法

方法1:修改Repository返回类型,手动转换

将Repository方法的返回值改为BigDecimal,在业务代码中手动转换为Price对象:

@Query("SELECT SUM(x.price) FROM YourEntity x WHERE ...")
BigDecimal sumPrice();

业务层调用示例:

BigDecimal sum = yourRepository.sumPrice();
Price totalPrice = sum != null ? new Price(sum) : null;

此方法简单直接,适合场景单一的情况。

方法2:注册Spring全局类型转换器

添加Spring原生Converter,让框架自动处理BigDecimal到Price的转换:

import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;

@Component
public class BigDecimalToPriceConverter implements Converter<BigDecimal, Price> {
    @Override
    public Price convert(BigDecimal source) {
        return source != null ? new Price(source) : null;
    }
}

若仍存在TupleBackedMap转换问题,可补充对应转换器:

import org.springframework.data.jpa.repository.query.AbstractJpaQuery;
import org.springframework.core.convert.converter.Converter;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
import java.util.Map;

@Component
public class TupleBackedMapToPriceConverter implements Converter<AbstractJpaQuery.TupleConverter.TupleBackedMap, Price> {
    @Override
    public Price convert(AbstractJpaQuery.TupleConverter.TupleBackedMap source) {
        if (source == null || source.isEmpty()) {
            return null;
        }
        BigDecimal value = (BigDecimal) source.values().iterator().next();
        return new Price(value);
    }
}

注册后Spring会自动识别并应用这些转换器。

方法3:使用构造函数投影

定义投影类,通过构造函数接收BigDecimal并转换为Price:

public class PriceProjection {
    private final Price totalPrice;

    public PriceProjection(BigDecimal totalPrice) {
        this.totalPrice = new Price(totalPrice);
    }

    public Price getTotalPrice() {
        return totalPrice;
    }
}

修改Repository查询语句,指定返回该投影:

@Query("SELECT new com.yourpackage.PriceProjection(SUM(x.price)) FROM YourEntity x WHERE ...")
PriceProjection sumPrice();

调用时直接从投影对象中获取Price实例即可。

方法4:自定义Repository实现

若以上方法不适用,可自定义Repository实现类,手动处理查询结果转换:

// 自定义Repository接口
public interface CustomYourRepository {
    Price sumPrice();
}

// 实现类
@Repository
public class CustomYourRepositoryImpl implements CustomYourRepository {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public Price sumPrice() {
        BigDecimal sum = (BigDecimal) entityManager.createQuery("SELECT SUM(x.price) FROM YourEntity x WHERE ...")
                .getSingleResult();
        return sum != null ? new Price(sum) : null;
    }
}

// 主Repository接口继承自定义接口
public interface YourRepository extends JpaRepository<YourEntity, Long>, CustomYourRepository {
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.21 02:33:31