簡體   English   中英

我可以使用Hibernate的條件在from子句中生成子查詢嗎?

[英]Can I use Hibernate's Criteria to generate a subquery in the from clause?

我們在項目中經常使用Criteria來動態生成查詢。 我真的很喜歡查詢的表達方式。 問題在於,我們發現無法使該特定查詢使用基於clientId的索引,因此我們需要對其進行更改。 這是正常工作的非索引查詢:

public List<EventInstance> getEventInstances(Date from, Date to, Integer clientId) {
    Session session = this.getSession();

    Criteria criteria = session.createCriteria(EventInstance.class);

    if(clientId != null){

        criteria.add(Restrictions.disjunction()
            .add(Restrictions.eq("clientId", clientId))
            .add(Restrictions.eq("team1ClientId", clientId))
            .add(Restrictions.eq("team2ClientId", clientId))
            );
    }

    if(from != null){
        criteria.add(Restrictions.ge("startTime", from));
    }

    if(to != null){
        criteria.add(Restrictions.le("startTime", to));
    }

    @SuppressWarnings("unchecked")
    List<EventInstance> events = criteria.list();

    this.releaseSession(session);
    return events;
}

該查詢只能使用startTime索引,而不能與任何clientId一起使用索引。 我發現以下查詢形式有效地使用了我們的索引,並且我想使用條件創建此查詢:

select * from ( select * from eventInstance where (clientId = 8 or team1ClientId = 8 or team2ClientId = 8) ) evtalias where evtalias.startTime < now()

我已經可以使用以下代碼在WHERE子句中進行子選擇:

public List<EventInstance> getEventInstances(Date from, Date to, Integer clientId){
    Session session = this.getSession();

    DetachedCriteria subSelectClient = DetachedCriteria.forClass(EventInstance.class);
    if(clientId != null){
        subSelectClient.add(Restrictions.disjunction()
            .add(Restrictions.eq("clientId", clientId))
            .add(Restrictions.eq("team1ClientId", clientId))
            .add(Restrictions.eq("team2ClientId", clientId))
            )
            .setProjection(Property.forName("id"));
    }


    Criteria criteria = session.createCriteria(EventInstance.class);

    if(clientId != null){
        criteria.add(Property.forName("id").in(subSelectClient));
    }

    if(from != null){
        criteria.add(Restrictions.ge("startTime", from));
    }

    if(to != null){
        criteria.add(Restrictions.le("startTime", to));
    }

    @SuppressWarnings("unchecked")
    List<EventInstance> events = criteria.list();

    this.releaseSession(session);
    return events;
}

這將生成如下查詢:

select * from eventInstance this_ where this_.id in (select this_.id as y0_ from eventInstance this_ where (this_.clientId=8 or this_.team1ClientId=8 or this_.team2ClientId=8)) and this_.startTime<=now();

使用索引比我的原始查詢更糟,並且不會在FROM中進行子選擇。

所以我的問題是,我可以按標准執行此操作嗎?還是堅持使用HQL甚至本機SQL。 或者,如果您知道如何創建可以解決我的問題的索引,但是從mysql文檔中了解到,這是不可能的。

這是我要創建的目標查詢的explain的輸出:

mysql> explain select * from ( select * from eventInstance where (clientId = 8 or     team1ClientId = 8 or team2ClientId = 8) ) evtalias where evtalias.startTime < now();
+----+-------------+---------------+-------------+-------------------------------+-----    ------------------+---------+------+------+------------------------------------------------    --------------+
| id | select_type | table         | type        | possible_keys                 | key                    | key_len | ref  | rows | Extra                                                        |
+----+-------------+---------------+-------------+-------------------------------+-----------------------+---------+------+------+--------------------------------------------------------------+
|  1 | PRIMARY     | <derived2>    | ALL         | NULL                          | NULL                   | NULL    | NULL |  288 | Using where                                                  |
|  2 | DERIVED     | eventInstance | index_merge | eijoin2,ei_client,team2,team1 | ei_client,team1,team2 | 5,5,5   | NULL |  300 | Using union(ei_client,team1,team2); Using where; Using index |
+----+-------------+---------------+-------------+-------------------------------+-----------------------+---------+------+------+--------------------------------------------------------------+
2 rows in set (0.00 sec)

這是來自休眠標准子查詢的解釋:

+----+--------------------+-------+-----------------+---------------------------------------+---------+---------+------+-------+-------------+
| id | select_type        | table | type            | possible_keys                         | key     | key_len | ref  | rows  | Extra       |
+----+--------------------+-------+-----------------+---------------------------------------+---------+---------+------+-------+-------------+
|  1 | PRIMARY            | this_ | ALL             | ei3                                   | NULL    | NULL    | NULL | 49434 | Using where |
|  2 | DEPENDENT SUBQUERY | this_ | unique_subquery | PRIMARY,eijoin2,ei_client,team2,team1 | PRIMARY | 4       | func |     1 | Using where |
+----+--------------------+-------+-----------------+---------------------------------------+---------+---------+------+-------+-------------+
2 rows in set (0.00 sec)

據我所知, Criteria和HQL都無法在from子句中生成帶有子查詢的查詢,因此您必須使用本機SQL。

暫無
暫無

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

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