2017-05-26 140 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