Hibernate - предотвращение ненужного объединения при использовании внешнего ключа в предложении where - PullRequest
5 голосов
/ 09 марта 2010

Я пытаюсь оптимизировать запросы к базе данных в Hibernate, но нашел блокиратор:

<class name="SupportedLanguageVO" table="AR_SUPPORTED_LANG" >
    <cache usage="read-only"/>
 <id name="Id" type="java.math.BigInteger">
  <column name="ID" sql-type="NUMBER(20)" not-null="true"/>
  <generator class="assigned"/>
 </id>
    <property name="OrderSeq" type="java.math.BigInteger">
  <column name="ORDER_SEQ" sql-type="NUMBER(20)" not-null="true"/>
 </property>
    <many-to-one name="Country" class="CountryVO" column="CTRY_CD_ID" cascade="none" >
    <many-to-one name="Language" class="LanguageVO" column="LANG_CD" cascade="none" >

    </class>

Первичным ключом страны является CTRY_CD_ID. Если я запускаю следующие критерии

  Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
            crit.createCriteria("Country").add(Restrictions.eq("_CountryCode", p_countrycode));
            crit.addOrder(Order.asc("OrderSeq"));

Я вижу, что hibernate объединяет таблицы ctry и AR_SUPPORTED_LANG. Зачем? Было бы лучше запустить

select * from AR_SUPPORTED_LANG where ctry_cd_id=?

sql, а не

select * from AR_SUPPORTED_LANG inner join ctry .... where ctry_cd_id=?

Можно ли заставить Hibernate выполнить первый запрос?

Ответы [ 3 ]

1 голос
/ 10 марта 2010

Почему? Было бы лучше бежать ...

Это не обязательно так, и на самом деле сильно зависит от того, как ваша база данных оптимизирует свои запросы. Вообще говоря, внутреннее объединение будет более эффективным, поскольку оно дает возможность значительно сократить область поиска. Конечно, с таблицей простого типа, содержащей всего пару десятков строк, это выглядит как перебор. Добавьте пару миллионов строк, и вы увидите разницу.

По аналогичной причине, как правило, оптимально добавлять любые подсказки запросов, которые вы можете присоединить. Например (переписать ваш запрос на HQL):

from AR_SUPPORTED_LANG inner join ctry c where c.cd_id=?

... должно быть ...

from AR_SUPPORTED_LANG inner join ctry c WITH c.cd_id=?

Предложение WITH - это специфичный для HQL метод добавления предложений AND к операторам JOIN.

1 голос
/ 10 марта 2010

Я думаю, вы можете расставить все точки. Вы должны применить эквалайзер непосредственно к объекту страны:

Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.add(Restrictions.eq("Country", p_country));
crit.addOrder(Order.asc("OrderSeq"));

Таким образом, если я хорошо помню, hibernate должен оптимизировать запрос так, как вы хотите. Но это означает, что вам нужен объект страны, а не только код страны.

1 голос
/ 10 марта 2010

Попробуйте явно установить режим выборки для ваших критериев:

crit.setFetchMode("Country", FetchMode.SELECT);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...