2017-05-26 173 views
1

我的應用程序中有一個性能問題。休眠使查詢太多

我有三個實體與下面的關係:

one Order => many OrderLines => Many Cards 

實體從數據庫負載需要太多的時間,在orderLines都裝有預先加載,而卡都含有延遲加載。爲了讓應用程序流暢,需要延遲加載。

我需要配置一個案件的急切加載,我需要幫助來做到這一點。

我使用jhsipster堆棧:春季啓動與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,爲每卡休眠執行兩個查詢,並與參加該請求不加載數據像渴望的配置。你有想法幫助我嗎?

非常感謝

+0

在第一個查詢使用別的東西作爲'order'和':order'因爲這是很明顯一個SQL關鍵字,這就是爲什麼休眠爲您提供了錯誤有。 –

回答

2

使用 「連接抓取」,以避免延遲加載。 「提取」連接允許使用單個選擇將關聯或值集合與其父對象一起初始化。這在收集的情況下特別有用。它有效地覆蓋了關聯和集合映射文件的外連接和惰性聲明。 查看加入更多的信息獲取: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); 
+0

加入抓取解決了第一個問題。現在我只有一個查詢。 第二個問題:「意外令牌順序」是因爲「order」是一個postgre關鍵字。 現在我有我的單元測試新問題: org.hibernate.LazyInitializationException:無法初始化代理 - 沒有會話 你有關於這個問題的想法? – nassim

+0

在列名稱周圍使用反引號(''),引號或雙引號。例如:'order' https://www.mkyong.com/hibernate/how-to-use-database-reserved-keyword-in-hibernate/ – Sudhakar

+0

我找到了另一個主題的解決方案。我添加了hibernate.jdbc。use_streams_for_binary:錯誤 在配置文件,它解決了這個問題。現在我期待着真正理解答案。 – nassim