Hibernate - Evitar desnecessária se juntar ao usar chave estrangeira na cláusula WHERE
-
18-09-2019 - |
Pergunta
I tentar otimizar as consultas de banco de dados em Hibernate, mas eu achei um bloqueador:
<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>
A chave primária do País é o CTRY_CD_ID
. Se eu executar os seguintes critérios
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.createCriteria("Country").add(Restrictions.eq("_CountryCode", p_countrycode));
crit.addOrder(Order.asc("OrderSeq"));
Eu posso ver, que o Hibernate se junta ao CTRY e as mesas AR_SUPPORTED_LANG. Por quê? Seria melhor para executar
select * from AR_SUPPORTED_LANG where ctry_cd_id=?
SQL em vez de
select * from AR_SUPPORTED_LANG inner join ctry .... where ctry_cd_id=?
Posso forçar o Hibernate para executar a primeira consulta?
Solução
Por quê? Seria melhor para executar ...
Isso não é necessariamente verdade, e na verdade depende muito de como seu banco de dados otimiza suas consultas. De um modo geral, juntando interna será mais eficiente porque tem a oportunidade de reduzir substancialmente o escopo da pesquisa. Claro que, com uma tabela de tipo simples, com apenas um par dúzia de linhas que parece um exagero. Adicione um par milhão de linhas e você verá a diferença.
Por uma razão semelhante, é geralmente melhor para adicionar quaisquer sugestões de consulta que você pode junta. Por exemplo (reescrevendo sua consulta no HQL):
from AR_SUPPORTED_LANG inner join ctry c where c.cd_id=?
... deve ser ...
from AR_SUPPORTED_LANG inner join ctry c WITH c.cd_id=?
A cláusula WITH é um método específico do HQL de adicionar e cláusulas de instruções JOIN.
Outras dicas
Tente explicitamente definir o modo de obtenção dos seus critérios:
crit.setFetchMode("Country", FetchMode.SELECT);
Eu acho que você pode dot-lo. Você deve aplicar o eq diretamente no objeto país:
Criteria crit = m_Session.createCriteria(SupportedLanguageVO.class);
crit.add(Restrictions.eq("Country", p_country));
crit.addOrder(Order.asc("OrderSeq"));
Dessa forma, se eu me lembro bem, hibernate deve otimizar a consulta da maneira que quiser. Mas isso significa que você precisa do objeto país, não só o código do país.