«MultipleBagFetchException: невозможно одновременно получить несколько сумок» при объединении трех таблиц глубины - PullRequest
2 голосов
/ 24 марта 2019

org.springframework.dao.InvalidDataAccessApiUsageException: org.hibernate.loader.MultipleBagFetchException: невозможно одновременно получить несколько пакетов: [Order.items, OrderItem.options];

Выше - этоИсключение я столкнулся, когда я присоединяюсь к трем таблицам, как показано ниже

OrderItemOption.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;
}

OrderItem.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;
}

Order.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;
}

И вот мой код 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())

Я пытаюсь получить объект Order, который содержит отфильтрованные отношения, чтобы я мог получить доступ к отфильтрованным дочерним элементам через объект заказа.и тип отношения должен быть List, а не Set.

, например, order.getItems (). get (0) .getOptions.get (0)

Как мне достичьэта цель?

Ответы [ 2 ]

0 голосов
/ 03 мая 2019

Если вы действительно не можете использовать Set вместо List:

Parent.class

@OneToMany(
    mappedBy = "parent",
    orphanRemoval = true,
    cascade = { CascadeType.PERSIST, CascadeType.MERGE }
)
@OrderColumn(name = "position")
private List<Child> childs = new ArrayList<>();

Child.class

@ManyToOne(fetch = FetchType.LAZY)
private Parent parent;

И создать столбец в дочерней таблице с именем, например, «позиция»

ALTER TABLE child ADD COLUMN position integer NOT NULL default 0

И если вы не можете использовать другие столбцы в таблице, их нужно запрашивать в списках по порядку. Или используйте идентификатор ребенка и пользовательский получатель.

@OrderColumn(name = "id_child", updatable = false, insertable = false)

public List<Child> getChilds() {
    childs.removeAll(Collections.singleton(null));
    return childs;
}
0 голосов
/ 24 марта 2019

Во избежание вышеуказанного исключения есть две возможности:

  1. Изменить List на Set
    или
  2. Использовать List, но не брать две сумки.Это означает, что не следует использовать fetchJoin() в обеих коллекциях.

Фильтрация:

Использование в тех случаях, когда коллекции условий не будут фильтроваться.Коллекции будут содержать все связанные объекты.Присоединение в JPA для создания условий для корневого объекта - Order.Это не то же самое, что в SQL.

Можно отфильтровать связанные коллекции, используя функцию JPA 2.1 JOIN ON.Это позволяет использовать дополнительные условия в ON пункте

, например, QueryDSL Left Join с дополнительными условиями в ON

...