まず質問を設定します。巨大な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つ多く作成されます。
これらの選択を削除する必要があります。彼らがそこにいなかった場合、クエリは正常に見え、効率的です!更新された更新クエリは完璧かつ動的です。
アイデア?
この類似した投稿をチェックアウトする:http://stackoverflow.com/questions/161224/what-are-the-differences-between-the-different-saving-methods-in-hibernate –