@OneToOne делает sql запрос на каждый объект в таблице

Рейтинг: 0Ответов: 1Опубликовано: 29.01.2023

Всем привет, сделал необходимые entity под БД:

@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "****", schema = "****")
public class ShopProductEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id", nullable = false)
    private Integer id;

    @OneToOne
    @JoinColumn(name = "sku_id", referencedColumnName = "id")
    private ShopProductSkusEntity sku;
}
@Getter
@Setter
@Accessors(chain = true)
@Entity
@Table(name = "****", schema = "*****")
public class ShopProductSkusEntity implements Serializable {

    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Id
    @Column(name = "id", nullable = false)
    private Integer id;

    @Basic
    @Column(name = "product_id", nullable = false)
    private Integer productId;

    @Basic
    @Column(name = "sku", nullable = false, length = 255)
    private String sku;
}

И когда делаю запрос на получение всех элементов таблицы:

public synchronized List<ShopProductEntity> getAllProducts() {
        return em.createQuery("SELECT a FROM ShopProductEntity a", ShopProductEntity.class)
                .getResultList();
    }

То вижу по логам Hibernate, что происходит первый запрпос на получение всех строк из ShopProductEntity, а потом для каждой записи - происходит отдельный запрос в ShopProductSkusEntity:

Hibernate: select shopproduc0_.id as id1_4_, shopproduc0_.sku_id as sku_id2_4_ from shop_product shopproduc0_
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
Hibernate: select shopproduc0_.id as id1_7_0_, shopproduc0_.product_id as product_2_7_0_, shopproduc0_.sku as sku3_7_0_ from shop_product_skus shopproduc0_ where shopproduc0_.id=?
и так далее . . .

А записей в ShopProductEntity порядка 180000 и Hibernate делает запросы не паралельно, а в одном потоке. И каждый запрос занимает где-то 0.2-0.3 мс, что приводит к неопределенному кол-во времени в ожидании, пока всё выгрузиться (явно более 1 часа).

Вопрос: Как оптимизировать этот момент? Может как-то можно указать Hibernate, чтобы он кэшировал сразу всю таблицу ShopProductSkusEntity и не обращался постоянно к БД? Или есть какие-то другие варианты, может это проблема N+1 и надо копать в эту сторону?

Ответы

▲ 0Принят

Исходя из комментариев под вопросом (спасибо Дмитрию и MrFylypenko) - выявил 2 решения, которые одинаково хорошо решают мою проблему:

  1. Принудительно использовать в HQL запросе left join fetch, что заставить Hibernate добавить в свой запрос left outer join и сразу выгрузить все необходимые строки из другой таблицы, вместо того чтобы делать отдельный запрос на каждую строку
  2. Просто использовать @ManyToOne