代码之家  ›  专栏  ›  技术社区  ›  HamoriZ

hibernate-在where子句中使用外键时避免不必要的连接

  •  5
  • HamoriZ  · 技术社区  · 14 年前

    我试图在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_支持的语言表。 为什么? 最好是跑

    select * from AR_SUPPORTED_LANG where ctry_cd_id=?
    

    SQL而不是

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

    我可以强制hibernate运行第一个查询吗?

    3 回复  |  直到 14 年前
        1
  •  1
  •   Civil Disobedient    14 年前

    为什么?最好是跑…

    这不一定是真的,实际上很大程度上取决于数据库如何优化查询。一般来说,内部连接将更有效,因为它有机会大大缩小搜索范围。当然,对于一个只有几十行的简单类型表来说,这看起来有点过头了。再加上几百万行,你就会看到区别了。

    出于类似的原因,通常最好添加任何可以加入的查询提示。例如(在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语句中。

        2
  •  1
  •   Péter Török    14 年前

    请尝试为条件显式设置提取模式:

    crit.setFetchMode("Country", FetchMode.SELECT);
    
        3
  •  1
  •   Thierry    14 年前

    我想你可以点它。 您应该将eq直接应用于country对象:

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

    这样,如果我记得很好的话,hibernate应该按照您想要的方式优化查询。但这意味着您需要country对象,而不仅仅是country代码。