简体   繁体   中英

Hibernate subselect with Criteria API: slow performance in MySql

I have a subselect query (like the one below) in my hibernate mapping XML file. The purpose of this is to setup a basic SQL query which will then have various restrictions added via the Criteria API. I am displaying data which can be sorted, filtered, and searched with support for pagenation, and so the Criteria API is very useful for this.

<class name="className" table="tableName">
    <subselect>
        select         x.col1         AS       ID,
                       c.col2         AS       a
                       ....
        from           table1         x,
                       table2         y
        where          x.id           =        y.id
                       ....
                       ....
    </subselect>
    <id name="ID" column="ID"/>
    <property name="a" column="a"/>
    ...
    ...
</class>

and the Java code will then add restrictions by doing something like

Criteria c = sessionFactory.getCurrentSession().createCriteria(tableName.class); c.add(Restrictions.allEq(m)); // where m is a hashmap containing column filters

However, it seems that the use of subselect to declare the basic query is causing very poor performance in MySQL. Hibernate puts the basic query into a subquery which is in the FROM clause of an outer query which has the added restrictions. So, just to be clear, Hibernate creates a query like A, whereas the query I want is B ie I don't want a subquery as it kills performance.

A:  select _tmp.*                         B: select  t1.col1,
    from (                                           t1.col2 
           select  t1.col1,                  from    table1  t1,
                   t1.col2                           table2  t2 
           from    table1  t1,               where   t1.id = t2.id
                   table2  t2                and     t1.col1 = 'blah' 
           where   t1.id = t2.id             order by t1.col desc 
           ...
          ) _tmp
     where _tmp.col1 = 'blah'
     order by _tmp.col2 desc

So my question is how do I create the basic query in Hibernate without using subselect that allows me to use the Criteria API? What's the best way to get Hibernate the run query B rather than query A?

I understand that I can create named queries in the mapping file and load them, but that loads a query which, although allows me to add certain restrictions, it isn't as good as Criteria as it doesn't allow options for sorting etc ...

So are there any other options besides using either

<hibernate-mapping>
 <class name="" table="">
    <subselect></subselect>
 </class>
</hibernate-mapping>

or  
<hibernate-mapping>
  <sql-query name="">   
    <return-scalar column="col" type="string"/>
  </sql-query>
</hibernate-mapping>

as the first option degrades performance through the use of subquery, and the second option doesn't allow me (to the best of my knowledge anyway?) to use the Criteria API .

I have a solution, so I'm adding it here for reference.

My requirement was to use Hibernate to retrieve data from multiple tables and filter the resultset using the Criteria API. Being fairly new to Hibernate and Criteria, I went for the option I deemed easiest at the time which was to hand-craft some raw SQL to pull the data together and filter that data using Criteria. The use of subselect was the only way I knew at the time to load a hand-crafted SQL statement for futher amendment by Criteria functions. This worked fine in terms of functionality, but as detailed above, performed very poorly when running against MySQL.

What I didn't realise I could do with Criteria is use Aliases to place restrictions on associations. So I've ditched the raw SQL, and used Hibernate to retrieve my parent data object and used Criteria Aliases to add restrictions on all required associations. This method performs in under 100ms compared to 5 seconds.

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