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 你知道这个问题吗? 在列名周围使用反引号 (``)、引号或双引号。如:order
mkyong.com/hibernate/…
我找到了另一个主题的解决方案。我在配置文件中添加了 hibernate.jdbc.use_streams_for_binary: false ,它解决了这个问题。现在我希望能真正理解答案。以上是关于Hibernate 查询太多的主要内容,如果未能解决你的问题,请参考以下文章
即使使用 @Fetch(FetchMode.JOIN),JPA + Hibernate 也会出现太多查询问题