2010-03-26 115 views
2

我有以下設置:CF9 HQL語句對於很多一對多和多目標

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文檔查看還沒有找到一個解決方案,不會給我一個錯誤。我的猜測是,解決方案非常簡單,我只是在想它...任何人有任何建議?

回答

4

我不相信這是做到這一點的最有效的方法,但是,它會產生我想

<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郵件列表上給了我什麼,我相信是最正確的解決這個問題張貼在這裏給大家:

「據我所知ORMExecuteQuery不處理列表參數,所以如果你想PARAM他們返回對象,你不得不這樣做

<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() /> 

喬恩謝謝!

+1

至少它是正確的,我會這樣做,如果我必須留在HQL(不寫自定義,更高效的SQL) – Henry 2010-03-27 00:40:10

+0

我已經添加了最正確的解決方案,以此答案的底部。 – 2010-03-29 20:57:11

0

這應該工作:

<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

+0

這實際上不會給我我想要的結果。這將給我任何列表110,113或125的功能,不僅列表與所有3個功能。 – 2010-03-26 19:43:34

+1

好的。我懂了。對困惑感到抱歉。然後你必須對結果進行分組並使用HAVING子句來檢查你的清單對象是否匹配* ALL *條件。看到你,亨利等。人。已經發布了cf-orm-dev Google小組的解決方案。 – 2010-03-27 09:36:04