2012-02-08 10 views
8

私は7つのテーブルを渡る複雑なクエリを持ち、Hibernateでそれを実装する方法を知りたいと思っています。Hibernate - 複数のテーブルから1つのオブジェクトへの複雑なクエリ

私の現在の試みは、session.createSQLQueryを使用してクエリを作成することです。結果を特定のエンティティにマップします。

これまでのように、私は1つのテーブルで1つのエンティティにしか作業していなかったとは思いますが、わかりません。複数のテーブルにまたがる複雑なクエリを使用することを指定する必要があるのはどこですか?それは私のコードの中だけにありますか?私のhbm.xmlファイル?私は私の現在の試みを超えて何かを考えることができません。ここで

は、私のクエリの例です:

String stringQuery = 
     "select WI.Customer_Id, CU.Card, CU.Code, "+ 
       "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
       "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
       "CO.City_Geo_Level, "+ 
       "CU.Address_id, CA.Name, "+ 
       "CU.Category_Id, "+ 
       "CU.Status, "+ 
       "Sum(MO.Charged_Points) as Charged_Points, "+ 
       "Sum(MO.Total_Money) as Total_Money, "+ 
       "Count(MO.id) as AmountTransWinner "+ 
     "from Promotions_Winner WI "+ 
     "join Customers CU "+ 
      "on WI.Customer_id = CU.id "+ 
     "join Personal_Info PI "+ 
      "on CU.Personal_Info_Id = PI.id "+ 
     "join Address AD "+ 
      "on CU.Address_Id = AD.id "+ 
     "join Countries CO "+ 
      "on AD.country_id = CO.id "+ 
     "join Campaigns CA "+ 
      "on CU.Campaign_Id = CA.id "+ 
     "join Movements MO "+ 
      "on WI.Movement_Id = MO.id "+ 
     "where WI.Promotion_Id = :pPromotionID "+ 
     "group by "+ 
      "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+ 
      "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
      "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
      "CO.City_Geo_Level, "+ 
      "CU.Address_id, CA.Name, "+ 
      "CU.Category_Id, "+ 
      "CU.Status"; 
+0

http://stackoverflow.com/questions/21374550/fetching-data-from-multiple-tables-in-hibernate-and-storing-the-result-in-a-bean/21379254を参照してください#21379254 – Touchstone

答えて

5

あなたはこのクエリを実行するSQLを必要としません。 HQLはうまくいくでしょう。そしてそのようなクエリはList<Object[]>を返します。それぞれObject[]には結果セットの行が含まれています。したがって、インデックス0の顧客ID、インデックス1のカードなどを見つけることができます。行をループし、各繰り返しで軽量オブジェクトのインスタンスを作成するだけで済みます。

は、私はこれが7つの表の結合で見ることができるように限りhttp://docs.jboss.org/hibernate/core/3.6/reference/en-US/html_single/#queryhql-select

+1

List を反復して軽量オブジェクトを手動で作成するのではなく、 'select new my.package.myLightWeightObject(t1.field1、t2.field2、t3.field3)'を使用して、myLightWeightObjectのコンストラクタを設定して適切なフィールド。そうすれば、Hibernateはリストの代わりにList を返します。 – digitaljoel

+0

JB Nizet、はい、私も知っていますが、リストを使用し、将来、他の人が現在のフィールドの間に新しいフィールドを1つ追加すると、もう動作しません。 私はdigitaljoelのアイデアが好きですが、私はそれを行う方法を理解していません。もう少し説明できますか? –

+0

はい。彼がコードを変更せずにデータベーステーブルを変更しても、それは動作しません。ユニットテストを実装し、ユニットテストでクエリが期待通りに機能することを確認します。どのように私(またはdigitaljoel)がそれよりも明確になるかわかりません。あなたは何を理解していますか?少なくとも何か試しましたか? –

0

を参照してください。 hibernateを使用している場合は、これらの各テーブルをエンティティにマップし、@ JoinColumnを使用してそれぞれの依存関係にマップします。これは発生を防ぐために休止状態になるSQLクエリの一種です。

+0

しかし、私はカウントと合計フィールドを持っています –

+0

次に、メソッドとしてgetTotalChargePoints()を持っています - それはあなたのビジネスロジックになります。そうすれば、毎回このクエリを呼び出す必要はありません。カウントのために、文字通りList.size()は、それが結合するアイテムのコレクション(1対多の関係のため)を行うでしょう –

3

最後に、私はこのコードを使用して解決できます。

String stringQuery = 
       "select " + 
         "CU.Card as card, " + 
         "CU.Fidely_Code as fidelyCode, "+ 
         "PI.Identity_Card as identityCard, " + 
         "PI.Name as name, " + 
         "PI.Surname as surname, " + 
         "PI.Gender as gender, "+ 
         "AD.Zip as zip, " + 
         "AD.Geo_Lat as geo_lat, " + 
         "AD.Geo_Long as geo_long, "+ 
         "CO.City_Geo_Level as cityGeoLevel, "+ 
         "CA.Name as campaignName, "+ 
         "CU.Status as status, "+ 
         "Sum(MO.Charged_Points) as pointsCharged, "+ 
         "Sum(MO.Total_Money) as amountPurchase, "+ 
         "Count(MO.id) as amountTransWinner "+ 
       "from Promotions_Winner WI "+ 
       "join Customers CU "+ 
        "on WI.Customer_id = CU.id "+ 
       "join Personal_Info PI "+ 
        "on CU.Personal_Info_Id = PI.id "+ 
       "join Address AD "+ 
        "on CU.Address_Id = AD.id "+ 
       "join Countries CO "+ 
        "on AD.country_id = CO.id "+ 
       "join Campaigns CA "+ 
        "on CU.Campaign_Id = CA.id "+ 
       "join Movements MO "+ 
        "on WI.Movement_Id = MO.id "+ 
       "where WI.Promotion_Id = :pPromotionID "+ 
       "group by "+ 
        "WI.Customer_Id, CU.Card, CU.Fidely_Code, "+ 
        "PI.Identity_Card, PI.Name, PI.Surname, PI.Gender, "+ 
        "AD.Zip, AD.Geo_Lat, AD.Geo_Long, "+ 
        "CO.City_Geo_Level, "+ 
        "CU.Address_id, CA.Name, "+ 
        "CU.Category_Id, "+ 
        "CU.Status "; 

     //Query query = this.getSession().createSQLQuery(stringQuery).addEntity("", PromotionsWinnerLittle.class); 
     //Query query = this.getSession().createSQLQuery(stringQuery).setResultSetMapping("PromotionsWinnerLittle"); 
     Query query = this.getSession().createSQLQuery(stringQuery) 
      .addScalar("card", StandardBasicTypes.LONG) 
      .addScalar("fidelyCode", StandardBasicTypes.LONG) 
      .addScalar("identityCard", StandardBasicTypes.STRING) 
      .addScalar("name", StandardBasicTypes.STRING) 
      .addScalar("surname", StandardBasicTypes.STRING) 
      .addScalar("gender", StandardBasicTypes.STRING) 
      .addScalar("zip", StandardBasicTypes.STRING) 
      .addScalar("geo_lat", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("geo_long", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("cityGeoLevel", StandardBasicTypes.LONG) 
      .addScalar("campaignName", StandardBasicTypes.STRING) 
      .addScalar("status", StandardBasicTypes.LONG) 
      .addScalar("pointsCharged", StandardBasicTypes.BIG_DECIMAL) 
      .addScalar("amountPurchase", StandardBasicTypes.LONG) 
      .addScalar("amountTransWinner", StandardBasicTypes.LONG)    
      .setResultTransformer(Transformers.aliasToBean(PromotionsWinnerLittle.class)); 

     //Query query = this.getSession().createSQLQuery(stringQuery); 

     query = query.setLong("pPromotionID", promotionID); 

     List lista = query.list(); 

私はジャスト部「として」選択とaddScalar + setResultTransformer

+0

このアプローチの問題は、データをプリミティブ型として受け取った場合、このデータをユーザー定義型のスキーマで作成された別のテーブルに書き込むと、問題が発生します。 – rakeeee

4

上でこれを行うには、次の2つの方法が彼らのある追加しました。

リストオブジェクトの配列を取得します。

List<Object[]> 

ここで、配列の要素の1つはクエリの1行を表します。

2.あなたは ResultTransformer休止状態機能を使用することができます - あなたのクエリの出力のための単純なクラスを作成します。 - ResultTransformerを作成します。

Ex。

- クエリにトランスを設定します。

Query query=session.createSQLQuery("SELECT * FROM employeedetail"); // You can use named query, SQL native also 
     query.setResultTransformer(new MyResultTransformer()); 
      List<Employee> employees=query.list(); 
関連する問題