簡體   English   中英

為什么休眠會生成約500個SQL查詢?

[英]Why hibernate generates ~500 SQL queries?

當試圖優化舊項目中由Hibernate 4.2生成的MySQ慢查詢時,我發現下面的代碼生成了近500個SQL查詢(有很多重復項):

class MyDAO {
    public List<Message> findMessages() {
        Session session = MyHibernateUtils.openSession();

        String queryStr = "SELECT DISTINCT m FROM Message m "
                + " LEFT JOIN fetch m.types types "
                + " LEFT JOIN fetch m.mainType mainType "
                + " LEFT JOIN fetch m.place place "
                + " LEFT JOIN fetch m.building building "
                + " LEFT JOIN fetch m.city city "
                + " LEFT JOIN fetch m.kind kind "
                + " LEFT JOIN fetch m.domain domain "
                + " LEFT JOIN fetch m.action action "
                + " LEFT JOIN fetch m.customParameterA customParameterA "
                + " LEFT JOIN fetch m.customParameterB customParameterB "
                + " LEFT JOIN fetch m.scheduleEvents scheduleEvents "
                + " LEFT JOIN fetch m.comments comments "
                + " LEFT JOIN fetch m.messageLastActivities messageLastActivities "
                + " LEFT JOIN fetch m.customListA customListA "
                + " LEFT JOIN fetch m.childEvents childEvents "
                + " LEFT JOIN fetch m.parentEvent parentEvent "
                + " WHERE ...";

        List<Message> messages;
        try {
            session.getTransaction().begin();

            Query query = session.createQuery(queryStr);
            query.setTimeout(10);

            messages = query.list();
            session.getTransaction().commit();
        } catch (RuntimeException e) {
            session.getTransaction().rollback();
            throw e;
        } finally {
            session.close();
        }

        return messages;
    }
}

如何避免有那么多SQL查詢?

我不知道這是否有幫助,但是實體之間存在許多onyToMany和manyToMany關系。

謝謝您幫忙。

您應該檢查休眠生成的查詢,以查看經常訪問哪個表。

您還必須join fetch與您的related entities相關的join fetch實體,請參見此處:

Hibernate正在執行多個選擇請求,而不是一個(使用join fetch)

我個人更喜歡使用帶注釋的@BatchSize()進行延遲加載,以保持較小的延遲查詢計數。 只需將Batch-Size設置為2,即可將查詢數量減少一半。

還可以查看@Cache Annotation,它可以顯着減少查詢數量。 (只需考慮所有幾乎靜態的內容,例如城市/建築物/類型/領域等)

根據您的關系設計, @OneToMany@ManyToManyFetch默認值為LAZY ,這意味着要在子實體中加載相關記錄(當您調用getter方法時),hibernate會再執行一次查詢以加載該記錄(例如: select * from foo where id = ? ),因此,如果加載的實體(主實體)包含許多子實體,例如ManyToManyOneToMany您將在控制台中看到許多查詢。 要使這些查詢無效,可以將Fetch設置為EAGER但是在優化中不建議這樣做。

@Entity
public class MainEntity {

@ManyToMany(Fetch = FetchType.EAGER)
public List<Foo> foos;

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM