Hibernateに、膨大な選択と更新の代わりに、単純な更新を実行させる
-
06-07-2019 - |
質問
最初に質問を設定します。
私が持っているのは、顧客、住所、注文、注文項目の4つのテーブルです。それぞれはHibernate Annotationsを使用してマップされ、Spring DAO / Servicesレイヤーを介してアクセスされます。
私がやろうとしているのは、重複した顧客をマージすることです。本当に必要なのは、顧客Bに関連付けられたすべての注文と住所、顧客Aを指すようにcustomer_id外部キーを更新する必要があることです。その後、顧客Bは無効ビットを設定する必要があります。
これらの単純なクエリをデータベースに送信する代わりに、hibernateはおかしくなり、大量のselectおよびupdateクエリを発行します。特に、注文に添付されているすべての注文アイテムを選択します(これは EAGER
で定義されており、この点は変更できないためです)。更新前にselectを取得して発生を停止するには、次のように通常の javax.persistence.Entity
の上にhibernateエンティティアノテーションを追加してみました:
@org.hibernate.annotations.Entity(dynamicUpdate = true, selectBeforeUpdate = false, dynamicInsert = true)
これは、テーブル内の単一のアイテムのみを更新する単純なクエリを除いて、影響がないように見えました。
次の休止条件を使用してオブジェクトを取得します:
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();
次に、すべての住所および注文オブジェクトを顧客Bから顧客Aに移動し、実行します
return (Customer) this.getHibernateTemplate().merge(customer);
両方の顧客オブジェクト。これにより、関連するすべてのオブジェクト(OrderItems、Products、ProductType、ProductPricingTmplなど)を取得する大量のselectステートメントが作成されます。
これらの選択を削除する必要があります!それらがない場合、クエリは正常に見え、効率的です! Update出力クエリは完璧で動的です。
アイデアはありますか
解決
手がかりは、merge()操作の選択にある可能性があります。 Hibernate javadocから:
指定されたオブジェクトの状態をコピーします で永続オブジェクトに 同じ識別子。ない場合 現在永続インスタンス セッションに関連付けられている場合、 ロードされます。
したがって、Hibernateに変更する前にすべてのデータを強制的にロードさせます。
update()などの別の操作を試してください:
永続インスタンスを更新します 指定された分離の識別子 インスタンス。
しかし、約束はありませんが、Hibernateはそれをロードする必要があると判断するかもしれません。 dynamicUpdates = true構成は、実際に悪化する可能性があります。動的更新を発行する前に、何を開始するかを知る必要があるためです。