【问题标题】:CF9 HQL Statement for many-to-many and Multiple Criteria多对多和多条件的 CF9 HQL 语句
【发布时间】:2011-02-01 00:53:09
【问题描述】:

我有以下设置:

Listing.cfc

component persistent="true"
{
    property name="ListingId" column="ListingId" type="numeric" ormtype="int" fieldtype="id" generator="identity"; 
        ...
    property name="Features" type="array" hint="Array of features" singularname="Feature" fieldtype="many-to-many" cfc="Feature" linktable="Listing_Feature" FKColumn="ListingId" inversejoincolumn="FeatureId";    
} 

Feature.cfc

component persistent="true" table="Feature" schema="dbo" output="false"
{
    property name="FeatureId" column="FeatureId" type="numeric" ormtype="int" fieldtype="id" generator="identity"; 
    property name="FeatureDescription" column="FeatureDescription" type="string" ormtype="string";
    ...    
    /*property name="Listings" fieldtype="many-to-many" cfc="Listing" linktable="Listing_Feature" fkcolumn="FeatureId" inversejoincolumn="ListingId" lazy="true" cascade="all" orderby="GroupOrder";*/

} 

我可以使用以下方法选择所有具有特定功能的列表:

<cfset matchingListings = ormExecuteQuery("from Listing l left join l.Features as feature where feature.FeatureId = :feature",{feature = 110}) />

这很好,但是,我希望能够选择所有具有多种功能的列表(例如同时具有“洗碗机”和“车库”的列表)

经过几个小时的谷歌搜索和浏览休眠文档后,仍未找到不会给我错误的解决方案。我的猜测是解决方案很简单,我只是想多了……有人有什么建议吗?

【问题讨论】:

    标签: hibernate orm coldfusion hql coldfusion-9


    【解决方案1】:

    我不认为这是最有效的方法,但是,它确实产生了我想要的结果

    <cfset matchingListings = ormExecuteQuery("Select l.ListingId from Listing l
      left join l.Features as featureone left join l.Features as featuretwo
      left join l.Features as featurethree 
      where featureone.FeatureId = 108
        and featuretwo.FeatureId = 110
        and featurethree.FeatureId = 113") />
    

    这只会为我提供具有我正在寻找的所有功能的列表,但是,它会加入并查看正在生成的休眠 SQL 日志:

    select listing0_.ListingId as col_0_0_ 
    from dbo.Listing listing0_ 
    left outer join Listing_Feature features1_ on listing0_.ListingId=features1_.ListingId 
    left outer join dbo.Feature feature2_ on features1_.FeatureId=feature2_.FeatureId
    left outer join Listing_Feature features3_ on listing0_.ListingId=features3_.ListingId 
    left outer join dbo.Feature feature4_ on features3_.FeatureId=feature4_.FeatureId 
    left outer join Listing_Feature features5_ on listing0_.ListingId=features5_.ListingId 
    left outer join dbo.Feature feature6_ on features5_.FeatureId=feature6_.FeatureId 
    where 1=1 
    and feature2_.FeatureId=108 
    and feature4_.FeatureId=110 
    and feature6_.FeatureId=113
    

    似乎在 HQL 中必须有更有效的方法来做到这一点


    cf-orm-dev 邮件列表上的 Jon Messer 为我提供了我认为最正确的解决方案,将其发布在此处供大家参考:

    “据我所知,ORMExecuteQuery 不处理列表参数,所以如果你想对它们进行参数化并返回对象,你必须执行类似的操作

    <cfset featureIds = [javaCast('int',108), javaCast('int',110), javaCast('int',113)] >
    
    <cfset q = ormGetSession().createQuery("
        select l.ListingId 
        from Listing l 
            join l.features as f 
        where f.FeatureId in (:features)
        group by l.ListingId
        having count(*) = #arrayLen(featureIds)#
    ") /> 
    
    <cfset q.setParameterList('features', featureIds) /> 
    
    <cfset matchingListings = q.list() />
    

    "

    谢谢乔恩!

    【讨论】:

    • 至少它是正确的,如果我必须留在HQL,我会这样做(不写自定义,更高效的SQL)
    • 我已经在这个答案的底部添加了最正确的解决方案。
    【解决方案2】:

    这应该可行:

    <cfset featurelist = "110,113,125"/>
    <cfset matchingListings = ormExecuteQuery("from Listing l left join l.Features as feature where feature.FeatureId IN (#featurelist#)")/>
    

    如果你想使用绑定参数,你将不得不做一些额外的工作,因为这次 hibernate 不喜欢 ColdFusion 列表和/或数组作为绑定参数。你可以找到一些额外的信息here

    【讨论】:

    • 这实际上不会给我想要的结果。这将为我提供任何具有 110、113 或 125 特征 ID 的列表,而不仅仅是具有所有 3 个特征的列表。
    • 好的。我知道了。对困惑感到抱歉。然后您必须对结果进行分组并使用 HAVING 子句来检查您的列表对象是否符合 ALL 条件。看到你,亨利等。人。已经向 cf-orm-dev Google 组发布了解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-15
    • 2018-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多