2

I have a performances problem into my application.

I have three entities with the relations below:

one Order => many OrderLines => Many Cards

The load of entities from database takes too much time, the orderLines are loaded with eager loading while Cards are loaded with lazy loading. Lazy loading is necessary to let the application fluent.

I need to configure eager loading for one case and I need help to do it.

I'm using jhsipster stack: spring-boot with JPA

I tried to write Hql query

@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);

I have un error: Unexpected token order (line 2)

I tried it with native query

@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);

But when i do

orderLine.getCard()

From code, Hibernate still do queries to get data from database and that causes my problem of performances.

Necessary code of entities:

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;
}

My code actually

{
    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
        }
    }

The problem is in the second foreach, for every card hibernate execute two queries and the request with join doesn't load datas like eager configuration. Have you an idea to help me?

Many thanks

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
nassim
  • 147
  • 10
  • In your first query use something else as `order` and `:order` as that is quite obviously a sql keyword, which is why hibernate gives you the error you have. – M. Deinum May 26 '17 at 08:18

1 Answers1

3

Use "join fetch" to avoid lazy loading. A "fetch" join allows associations or collections of values to be initialized along with their parent objects using a single select. This is particularly useful in the case of a collection. It effectively overrides the outer join and lazy declarations of the mapping file for associations and collections. See the more information on 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);
Sudhakar
  • 3,104
  • 2
  • 27
  • 36
  • Join fetch solved the first problem. Now i have only one query. The second problem: "unexpected token order" was because of "order" is a postgre key word. Now I have new problem with my unit tests: org.hibernate.LazyInitializationException: could not initialize proxy - no Session Have you an idea about the problem ? – nassim May 26 '17 at 12:44
  • using backticks (``), quotes or double quotes around the column name. eg:`order` https://www.mkyong.com/hibernate/how-to-use-database-reserved-keyword-in-hibernate/ – Sudhakar May 26 '17 at 13:04
  • I found a solution on another topic. I added hibernate.jdbc.use_streams_for_binary: false on config file and it solved the problem. Now I'm looking to realy understand the answer. – nassim May 26 '17 at 15:13