简体   繁体   中英

Hibernate - how to avoid the n+1 issue while keeping a good throughput with @ManyToOne association?

I have a class Entry which has two fields serving auditing purposes: startAuditAction and endAuditAction . One audit action can affect several entries, therefore the class Entry describes ManyToOne relationships as follows:

public class Entry{
    @Id
    @Column(nullable = false)
    protected String path;

    @Id
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(nullable = false, name = "start_action_id")
    protected AuditAction startAction;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(updatable = true, nullable = true, name = "end_action_id")
    protected AuditAction endAction;
}

I want to retrieve instances of Entry based on conditions on the path field and the audit fields. For example to retrieve entries which have not yet been deleted, the HQL would look something like that:

SELECT DISTINCT entry FROM ENTRY_TABLE entry JOIN FETCH entry.startAction startAct LEFT JOIN FETCH entry.endAction endAct WHERE entry.path LIKE myPath and endAct IS NULL

I am using lazy loading together with JOIN FETCH to avoid the N+1 problem while still being able to access the audit fields. However, I have two problems with this:

  • Firstly, this really does not seem clean to me: if I know I want to access the audit fields (namely the audit actions timestamp), then they should not be lazy loaded. But if I use eager loading I am facing the n+1 problem even if I use JOIN FETCH (and in that case I do not understand why fetch = FetchType.EAGER would ever be useful)...
  • Secondly, even though I am avoiding the n+1 problem and therefore firing less SQL queries, I get some performance issues for the overall use of my database, probably because of the joins.

What is the proper way to avoid firing additional queries while preserving a good throughput ?

Thanks!

1- Using join fetch is useful when you have FetchType.LAZY in a field that you know you'll need in that specific case whereas using FetchType.EAGER will force that entity to always load the collection independently from the query

(eg with your same configuration example you can do multiple query and only when you need the collection use the JOIN FETCH )

2- You probably have problems somewhere else, i doubt the join is what is slowing you down

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM