Hibernate 查询太多

Posted

技术标签:

【中文标题】Hibernate 查询太多【英文标题】:Hibernate make too much queries 【发布时间】:2017-10-27 01:27:39 【问题描述】:

我的应用程序存在性能问题。

我有三个具有以下关系的实体:

one Order => many OrderLines => Many Cards

从数据库中加载实体需要太多时间,orderLines 是通过预先加载加载的,而 Cards 是通过延迟加载加载的。延迟加载是让应用流畅的必要条件。

我需要为一个案例配置预加载,我需要帮助。

我正在使用 jhsipster 堆栈:spring-boot with JPA

我尝试写 Hql 查询

@Query(value = "from Order as order "
        + "inner join order.orderLines as orderLines "
        + "inner join orderlines.cards gc "
        + "where order.id= :order")
Order findWithDependencies(@Param("order")Long order);

我有一个错误:意外的令牌订单(第 2 行)

我用原生查询试过了

@Query(value = "select * "+ 
        "from order_table ot "+
        "left join order_line ol ON ot.id = ol.order_id "+
        "left join  giftcard gc ON gc.orderline_id = ol.id "+
        "where ot.id=:order", nativeQuery= true)
Order findWithDependenciesNative(@Param("order")Long order);

但是当我这样做时

orderLine.getCard()

从代码中,Hibernate 仍然执行查询以从数据库中获取数据,这导致了我的性能问题。

实体的必要代码:

public class Order implements Serializable 
    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "order_id", nullable = false)
    @Size(min = 1)
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @JsonProperty("detail")
    @Valid
    private List<OrderLine> orderLines = new ArrayList<>();

public class OrderLine extends AbstractAuditingEntity implements Serializable, Comparable 
    @OneToMany
    @JoinColumn(name = "orderline_id")
    @JsonIgnore
    @Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    private Set<Giftcard> giftcards = new HashSet<>();


public class Giftcard extends AbstractAuditingEntity implements Serializable, Comparable 
    @ManyToOne(optional = true)
    @JoinColumn(name= "orderline_id")
    @JsonIgnore
    private OrderLine orderLine;

我的代码实际上


    Order order = orderRepository.findWithDependenciesNative(linkFile.getOrder());
    //Some code
    List<OrderLine> orderLines = order.getOrderLines();
    orderLines.sort(Comparator.comparing(OrderLine::getId));
    for (OrderLine orderLine : orderLines) 
        Stream<Card> cards = orderLine.getCards().stream().sorted(Comparator.comparing(Card::getCardNumber));
        for (Card card : cards.collect(Collectors.toList())) 
        //Some code
        
    

问题出在第二个 foreach 中,对于每个卡休眠执行两个查询,并且带有 join 的请求不会像 Eager 配置那样加载数据。你有什么想法可以帮助我吗?

非常感谢

【问题讨论】:

在您的第一个查询中,使用其他名称作为 order:order,因为这显然是一个 sql 关键字,这就是为什么 hibernate 会出现错误。 【参考方案1】:

使用“join fetch”来避免延迟加载。 “获取”连接允许使用单个选择来初始化值的关联或集合以及它们的父对象。这在集合的情况下特别有用。它有效地覆盖了关联和集合的映射文件的外部连接和惰性声明。 更多join fetch信息见:Difference between JOIN and JOIN FETCH in Hibernate

@Query("Select order from Order as order "
        + "inner join fetch order.orderLines as orderLines "
        + "inner join fetch orderlines.cards gc "
        + "where order.id= :order")
Order findWithDependencies(@Param("order")Long order);

【讨论】:

Join fetch 解决了第一个问题。现在我只有一个查询。第二个问题:“unexpected token order”是因为“order”是postgre的关键词。现在我的单元测试出现了新问题:org.hibernate.LazyInitializationException: could not initialize proxy - no Session 你知道这个问题吗? 在列名周围使用反引号 (``)、引号或双引号。如:ordermkyong.com/hibernate/… 我找到了另一个主题的解决方案。我在配置文件中添加了 hibernate.jdbc.use_streams_for_binary: false ,它解决了这个问题。现在我希望能真正理解答案。

以上是关于Hibernate 查询太多的主要内容,如果未能解决你的问题,请参考以下文章

即使使用 @Fetch(FetchMode.JOIN),JPA + Hibernate 也会出现太多查询问题

Hibernate与缓存的连接太多

Hibernate 花费了太多时间并执行了一些神秘的操作。

Hibernate查询方式

Spring JPA - Hibernate:批量插入执行太多选择 nextval('sequence')

java.net.SocketException:Spring Hibernate Tomcat 打开的文件太多