2011-07-07 10 views
1

私はLocationとIndustryの2つのエンティティとそれらの間のリンクテーブルを持っています。私は2つのエンティティ間で両方向に多対多の関係を設定しました。HQLとの多対多リレーションに対する最適以下のクエリ

検索クエリで、業種リストに関連付けられた[地域]を選択しようとしています。

基準APIを論じようとしている日と数日後、私はHQLに落として基準APIを放棄することに決めました。しかし、それでも私にとってうまくいきません - このHQLクエリを手書きで書くかどうかにかかわらず、または基準APIにそれをさせるかどうかにかかわらず、私は同じ結果をもたらします。

私は2つの方法で右の結果を生成するために管理 - 次のように:

var q = Data.Query("select distinct loc from Location loc join loc.Industries ind where ind in (:ind)"); 

q.SetParameterList("ind", new Industry[] { Data.GetIndustry(4), Data.GetIndustry(5) }); 

そして、(良い)そのように:残念ながら

var q = Data.Query("select distinct loc from Location loc join loc.Industries ind where ind.id in (:ind)"); 

q.SetParameterList("ind", new int[] { 4, 5 }); 

、結果の両方を次善のクエリで:

select distinct 
    location0_.Id as Id16_, 
    location0_.Name as Name16_, 
    (etc.) 
from Location location0_ 
    inner join LocationIndustry industries1_ 
    on location0_.Id=industries1_.LocationId 
    inner join Industry industry2_ 
    on industries1_.IndustryId=industry2_.Id 
where 
    industry2_.Id in (? , ?) 

余分な結合はなぜですか?

NHは、クエリに含まれる唯一のインダストリプロパティであるIndustry.IdプロパティがLocationIndustryリンクテーブルに格納されていることを知るには十分スマートではないため、インダストリアルへの余分な参加は必要ありませんテーブル自体?

または何か間違っていますか?

理想的には、私にとって最も直感的なことは、書くことのようになります。

from Location loc where loc.Industries in (:ind) 

は、これは動作しません - それは、エラーをスローし、それが産業財産について知らないと言います。インダストリアルはプログラミング面での「財産」であり、実際にはDBMSの観点からは「関係」なのではないかと思います。

このクエリをHQLに書き込む最も簡単で効率的な方法は何ですか?

ありがとうございます!

+0

興味深い質問です。しかし、追加結合の有無にかかわらず、重要な違いを測定しましたか?そして、ジョイン・テーブルに外部キー制約がなく、レコードが存在しない既存の業界を扱うために余分なジョインが行われるのでしょうか? –

+0

それは可能性のある説明の1つですが、うまく設計され、適切に管理されたデータベースには存在してはならない不整合なデータを説明するのは難しいです。これは単純に実装されていない最適化の可能性が高いと思われますか? –

答えて

2

あなたが使用しているマッピング戦略では、この余分な結合を避けることはできません。

あなたは仲介クラスを使用して、それを避けることができますが、これは、あなたがこのようなクラス構造が必要です意味します:

public class Industry { 
    //Other stuff 
    public virtual List<LocationIndustry> LocationIndustries {get; set:;} 
} 

public class LocationIndustry { 
    public virtual Location Location {get; set;} 
    public virtual Industry Industry {get; set;} 
} 

public class Location { 
    //normal stuff 
    public virtual IList<LocationIndustry> LocationIndustries {get; set;} 
} 

次にあなたがLocationIndustryクラスに照会し、Locationに参加避けることができます。

+0

+1とありがとうが、私はすでにこのオプションを検討していましたが、私はそれが醜いと思っています - 私はドメインモデルを歪ませて無用なエンティティを導入したくありません。それは、関連付けが追加/削除されたときに、より多くのオブジェクトを管理し、2倍の関係を維持しなければならないことを意味します。実際 –

+0

(私が... NHのようにもモンスターがインピーダンス不整合のあらゆる側面に対処することができないことを考え始めています)、これはあなたが、柔軟性のためにパフォーマンスを取引されているような状況の一つです。この状況でSQLQueryまたは名前付き問合せを使用できますか? SQLでクエリを記述しても、それをオブジェクトにマップできます。 –

+0

nh3.1であれば、hqlで新しい 'with'構文を使用して、in節を結合に追加することができます。しかし、これは、多対多の関係でそれを使用する場合には盗聴されます。 –

関連する問題