2009-06-17 5 views
0

まず質問を設定します。巨大なselectではなく、単純な更新を行うためにHibernateを取得する

私が持っているものは、4つ以上のテーブル:Customer、Address、Order、OrderItemsです。それぞれは、Hibernate Annotationを使用してマップされ、SpringのDAO/Servicesレイヤーを介してアクセスされます。

私がしようとしているのは、重複する顧客を一緒にマージすることです。つまり、顧客Bに関連するすべての注文と住所が顧客Aを指すようにcustomer_id外部キーを更新する必要があるため、顧客Bは無効ビットを設定する必要があります。

これらの単純なクエリをデータベースに送信するのではなく、hibernateが狂ってしまい、大量の選択クエリを発行してクエリを更新します。特に、オーダーに添付されたすべてのオーダーアイテムを選択します(これはEAGERと定義されているため、このポイントは変更できません)。これはそれだけで一つの項目を更新単純なクエリを除き、何ら影響を及ぼさないように見えた

@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = false, dynamicInsert = true) 

:私はのような定期的なjavax.persistence.Entityの上に休止状態のエンティティアノテーションを追加してみましたが起こって停止するように更新前の選択を取得するには表。

私は、次の休止状態の基準を使用してオブジェクトを取得する:

  Criteria c1 = null; 
      Criteria c2 = null; 
      Criteria c = session.createCriteria(Customer.class); 
      c.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY); 

      if(resultLimit>0) c.setMaxResults(resultLimit); 
      if(timeout>0) c.setTimeout(timeout); 
      for(String filter: sqlFilters) { 
       if(filter.indexOf("{alias}.customer_")!=-1) c.add(Restrictions.sqlRestriction(filter)); 
       else if(filter.indexOf("{alias}.address_")!=-1 && addrsAttached) { 
        if(c1==null) 
         c1 = c.createCriteria("addresses").setFetchMode("type", FetchMode.JOIN); 
        c1.add(Restrictions.sqlRestriction(filter)); 
       } else if(filter.indexOf("{alias}.order_")!=-1 && ordersAttached) { 
        if(c2==null) 
         c2 = c.createCriteria("orders").setFetchMode("orderItems", FetchMode.SELECT); 
        c2.add(Restrictions.sqlRestriction(filter)); 
       } 
      } 
      return (List<Customer>) c.list(); 

それから私は、顧客Aに顧客Bからのアドレスと注文オブジェクトのすべてを移動し、両方の顧客に

return (Customer) this.getHibernateTemplate().merge(customer); 

を実行しますオブジェクト。これにより、関連するすべてのオブジェクト(OrderItems、Product、ProductType、ProductPricingTmplなど)を取得するための選択文が1つ多く作成されます。

これらの選択を削除する必要があります。彼らがそこにいなかった場合、クエリは正常に見え、効率的です!更新された更新クエリは完璧かつ動的です。

アイデア?

+0

この類似した投稿をチェックアウトする:http://stackoverflow.com/questions/161224/what-are-the-differences-between-the-different-saving-methods-in-hibernate –

答えて

2

手がかりは、あなたの選択したmerge()操作にあるかもしれません。 HibernateのJavadocのから:

は 同じ識別子を持つ永続オブジェクトに指定されたオブジェクト の状態をコピーします。 の永続インスタンスが現在セッションに関連付けられている場合、 は、 にロードされます。

これで、データを変更する前にすべてのデータをロードするように強制しています。 所与取り外しインスタンスの識別子と永続的インスタンスを更新

は、更新()のように、異なる動作をしてみてください。

しかし、Hibernateは約束はしていないが、とにかくそれをロードする必要があると判断するかもしれない。 dynamicUpdates = trueの設定は、動的更新を発行する前に開始する内容を知る必要があるため、実際にはそれを悪化させる可能性があります。

関連する問題