加入三个深度表时“MultipleBagFetchException:无法同时获取多个袋子”

cra*_*udy 6 java spring hibernate jpa querydsl

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.loader.MultipleBagFetchException: 不能同时取多个包: [Order.items, OrderItem.options];

以上是我加入如下三个表时遇到的一个例外。

订单项选项.java

@Entity
public class OrderItemOption {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "item_option_id")
  private Long id;

  @Column(name = "item_id", nullable = false)
  private Long itemId;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(
      name = "item_id",
      referencedColumnName = "item_id",
      insertable = false,
      updatable = false
  )
  private OrderItem orderItem;
}
Run Code Online (Sandbox Code Playgroud)

订单项.java

@Entity
public class OrderItem {
  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "item_id")
  private Long id;

  @Column(name = "order_id", nullable = false)
  private Long orderId;

  @ManyToOne(fetch = FetchType.LAZY)
  @JoinColumn(
      name = "order_id",
      referencedColumnName = "order_id",
      insertable = false,
      updatable = false,
      nullable = false
  )
  private Order order;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "orderItem")
  @OrderBy("item_option_id ASC")
  private List<OrderItemOption> options;
}
Run Code Online (Sandbox Code Playgroud)

订单.java

@Entity
public class Order {
  @Id
  @Column(name = "order_id", nullable = false)
  private Long id;

  @OneToMany(fetch = FetchType.LAZY, mappedBy = "order")
  @OrderBy("item_id ASC")
  private List<OrderItem> items;
}
Run Code Online (Sandbox Code Playgroud)

这是我一次加入他们的 QueryDSL 代码。

final QOrder order = QOrder.order;
final QOrderItem item = QOrderItem.orderItem;
final QOrderItemOption option = QOrderItemOption.orderItemOption;

from(order)
.leftJoin(order.items, item).fetchJoin()
.leftJoin(item.options, option).fetchJoin()
.where(
    order.id.eq(orderId)
        .and(item.id.in(itemIds))
        .and(option.id.in(optionIds))
)
.fetchOne())
Run Code Online (Sandbox Code Playgroud)

我想要做的是获取包含过滤关系的 Order 对象,以便我可以通过 order 对象访问过滤的子项。并且关系的类型应该是一个列表,而不是一个集合。

例如, order.getItems().get(0).getOptions.get(0)

我怎样才能实现这个目标?

Pet*_*ály 5

为避免上述异常,有两种可能性:

  1. 更改ListSet
  2. 使用List但不要取两个袋子。这意味着不要fetchJoin()在两个集合上使用。

过滤:

使用 where 条件集合不会被过滤。集合将包含所有关联的对象。加入 JPA 是为了在根对象 - 订单上创建条件。它与 SQL 中的不同。

可以使用 JPA 2.1JOIN ON功能过滤关联的集合。这允许ON子句中的附加条件

参见示例QueryDSL Left Join with additional conditions in ON