ID とタイプのみを持つ nhibernate でエンティティを削除するにはどうすればよいでしょうか?
-
19-09-2019 - |
質問
NHibernate 2.1 を使用して、ID とタイプ (マッピングなど) だけを持つエンティティを削除するにはどうすればよいでしょうか?
解決
遅延読み込みを使用している場合、Load はプロキシのみを作成します。
session.Delete(session.Load(type, id));
NH 2.1 では HQL を使用できます。実際にどのように見えるかはわかりませんが、次のような感じです。 これは SQL インジェクションの影響を受けることに注意してください - 可能であれば、代わりに SetParameter() を使用してパラメータ化されたクエリを使用してください
session.Delete(string.Format("from {0} where id = {1}", type, id));
編集:
Load の場合、Id 列の名前を知っている必要はありません。
それを知る必要がある場合は、NH メタデータによって取得できます。
sessionFactory.GetClassMetadata(type).IdentifierPropertyName
別の編集。
session.Delete()
エンティティをインスタンス化しています
session.Delete() を使用する場合、NH はとにかくエンティティをロードします。最初は好きではありませんでした。それから私は利点に気づきました。エンティティが継承、コレクション、または「任意の」参照を使用する複雑な構造の一部である場合、実際にはより効率的です。
たとえば、クラスの場合、 A
そして B
どちらも継承します Base
, 、テーブル内のデータを削除しようとしません B
実際のエンティティが次のタイプの場合 A
. 。これは、実際のオブジェクトをロードしない限り不可能です。これは、継承された型が多数あり、それぞれが多くの追加テーブルで構成されている場合に特に重要です。
のコレクションがある場合も同じ状況が発生します。 Base
s、これはたまたますべてのインスタンスです A
. 。コレクションをメモリにロードするときに、NH はコレクションを削除する必要がないことを認識します。 B
-もの。
エンティティの場合 A
のコレクションを持っています B
s、これには以下が含まれます C
s (など)、何も削除しようとしません。 C
のコレクションのとき B
s は空です。これはコレクションを読み取る場合にのみ可能です。これは、C 自体が複雑で、さらに多くのテーブルを集約する場合などに特に重要です。
構造が複雑で動的であればあるほど、実際のデータを「盲目的に」削除するよりもロードする方が効率的になります。
HQL 削除には落とし穴がある
HQL はデータをメモリにロードしないように削除します。しかし、HQL 削除はそれほど賢明ではありません。基本的に、エンティティ名を対応するテーブル名に変換し、それをデータベースから削除します。さらに、一部の集約された収集データが削除されます。
単純な構造では、これは適切かつ効率的に機能する可能性があります。複雑な構造では、すべてが削除されるわけではなく、制約違反や「データベース メモリ リーク」が発生します。
結論
NHでの削除の最適化も試してみました。NH の方がまだ賢く、「問題なく動作」し、通常は十分に高速であるため、ほとんどの場合は諦めました。私が作成した最も複雑な削除アルゴリズムの 1 つは、NH マッピング定義を分析し、そこから削除ステートメントを構築することです。そして、当然のことですが、削除する前にデータベースからデータを読み取ることなしには不可能です。(主キーのみをロードするように縮小しました。)