2010-03-09 16 views
5

trato de optimizar las consultas de bases de datos en hibernación, pero he encontrado un bloqueador:Hibernate - Evitar innecesarias unirse al utilizar la clave externa en la cláusula where

<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> 

La clave principal del país es el CTRY_CD_ID. Si me quedo con los siguientes requisitos

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

puedo ver, que se une a la hibernación ctry y las mesas AR_SUPPORTED_LANG. ¿Por qué? Sería mejor correr

select * from AR_SUPPORTED_LANG where ctry_cd_id=? 

SQL en lugar de

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

¿Puedo forzar a Hibernate para ejecutar la primera consulta?

Respuesta

1

¿Por qué? Sería mejor ejecutar ...

Eso no es necesariamente cierto, y de hecho depende en gran medida de cómo su base de datos optimiza sus consultas. En términos generales, la unión interna será más eficiente porque tiene la oportunidad de reducir enormemente el alcance de la búsqueda. Por supuesto, con una tabla de tipos simple con solo un par de docenas de filas, parece excesivo. Agrega un par de millones de filas y verás la diferencia.

Por una razón similar, generalmente es óptimo agregar cualquier sugerencia de consulta que pueda unir. Por ejemplo (reescritura de la consulta en HQL):

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

... tiene que ser ...

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

La cláusula es un método HQL-específica de agregar y cláusulas de instrucciones JOIN.

1

intente configurar explícitamente el modo de captar para sus requisitos:

crit.setFetchMode("Country", FetchMode.SELECT); 
1

Creo que puedes puntearlo. Debe aplicar el eq directamente sobre el objeto País:

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

De esa manera, si recuerdo bien, Hibernate debe optimizar la consulta de la manera deseada. Pero eso significa que necesita el objeto del país, no solo el código del país.

+0

Desafortunadamente no tengo el objeto, solo el código de país :-( – HamoriZ

+0

¿Es el código de país el id de la tabla de país? Si lo es, hibernate no le importaría si construye el objeto a mano sin cargarlo desde el db, siempre y cuando llene el campo id (como por ejemplo: crit.add (Restrictions.eq ("Country", new CountryVO (p_country_code)));) – Thierry

Cuestiones relacionadas