【问题标题】:Hibernate - Avoiding unnecessary join when using foreign key in where clauseHibernate - 在 where 子句中使用外键时避免不必要的连接
【发布时间】:2011-01-25 12:37:34
【问题描述】:

我尝试在 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=?

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

【问题讨论】:

    标签: sql hibernate fetch hibernate-mapping


    【解决方案1】:

    为什么?跑起来会更好……

    这不一定正确,实际上很大程度上取决于您的数据库如何优化其查询。一般来说,内连接会更有效,因为它有机会大大缩小搜索范围。当然,对于一个只有几十行的简单类型表,它看起来有点矫枉过正。添加几百万行,您就会看到差异。

    出于类似的原因,通常最好将任何可以添加到联接的查询提示添加到联接中。例如(用 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】:

      尝试为您的条件显式设置获取模式:

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

      【讨论】:

        【解决方案3】:

        我认为你可以点它。 您应该将 eq 直接应用于国家对象:

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

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

        【讨论】:

        • 不幸的是我没有对象,只有国家代码:-(
        • 国家代码是国家表的id吗?如果是这样,只要填充 id 字段(例如:crit.add(Restrictions.eq("Country", new CountryVO( p_country_code)));)
        猜你喜欢
        • 1970-01-01
        • 2012-09-30
        • 2012-09-22
        • 2011-12-23
        • 1970-01-01
        • 1970-01-01
        • 2012-02-02
        • 1970-01-01
        • 2017-05-27
        相关资源
        最近更新 更多