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

MultipleBagFetchException与HttpMessageNotWritableException异常求解

问题根因说明

MultipleBagFetchException的触发原因是Hibernate不支持同时对两个及以上的集合类型关联属性执行急加载(EAGER)。你之前的全局EAGER配置会触发所有涉及Expense的查询都自动加载关联属性,如果关联的Shop或Currency实体中还存在其他EAGER加载的List类型关联,就会触发该异常。
而你切换为懒加载后接口抛出HttpMessageNotWritableException,是因为Spring MVC序列化Expense对象时,关联的shop、currency还只是未初始化的代理对象,session已经关闭无法加载数据导致的。

可行解决方案(无需修改集合类型)

方案1:使用实体图按需指定加载关联属性(推荐)

  1. 先将Expense实体的关联属性改回懒加载:
@ManyToOne(fetch = FetchType.LAZY)
private Shop shop;

@ManyToOne(fetch = FetchType.LAZY)
private Currency currency;
  1. 在你的ExpenseRepository的findAll方法上添加@EntityGraph注解,指定查询时同步加载shop和currency:
import org.springframework.data.jpa.repository.EntityGraph;
import java.util.List;

public interface ExpenseRepository extends JpaRepository<Expense, Long> {
    @EntityGraph(attributePaths = {"shop", "currency"})
    List<Expense> findAll();

    // 其他查询方法如果需要关联数据也可以加同样的注解
    @EntityGraph(attributePaths = {"shop", "currency"})
    List<Expense> findAllByShopId(Long shopId);
}

这种方式只有标注了实体图的查询会加载关联属性,其他查询默认走懒加载,既不会触发MultipleBagFetchException,也能保证findAll接口返回的对象关联属性已经初始化,可以正常序列化。

方案2:使用JPQL的JOIN FETCH手动指定关联加载

如果你是用自定义JPQL查询,可以直接在查询语句中写JOIN FETCH指定要加载的关联:

import org.springframework.data.jpa.repository.Query;
import java.util.List;

public interface ExpenseRepository extends JpaRepository<Expense, Long> {
    @Query("SELECT e FROM Expense e JOIN FETCH e.shop JOIN FETCH e.currency")
    List<Expense> findAll();
}

效果和实体图完全一致,适合需要自定义查询逻辑的场景。

临时规避方案

如果暂时不想修改查询逻辑,可以在application.properties/yml中添加配置,关闭序列化时的空Bean报错:

spring.jackson.serialization.fail-on-empty-beans=false

但该方案只是跳过了序列化报错,实际返回的关联字段值为null,仅适合临时调试使用,不建议线上使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:09:03