2016-10-05 5 views
0

私は休止状態に関してかなりのピクルスに自分自身を見つけました。私は自分のWebアプリケーションの開発を開始したときにどこにいても "熱心な"読み込みをしていましたので、子供、両親などに簡単にアクセスできました。Hibernateグッドプラクティス、レイジー/ eagerローディングとセーブ/削除の子供たち(助けて私を助けてください)

しばらくして、削除されたオブジェクトを再保存しました。複数のstackoverflowスレッドは、オブジェクトをすべてのコレクションから削除しなければならないことを示唆しました。これらの提案を読むことは、私の関係が本当にシンプルではなく、私のコードを一種のように見せかける複数のオブジェクトを反復しなければならなかった醜いと私はこれが最高のアプローチだったかどうか疑問に思った。

たとえば、Employee(ユーザーが複数の異なる従業員として行動できるという意味でUserに属している)を削除する場合。従業員がフィードバックを党に残すことができるので、従業員は複数のフィードバックを持ち、党は複数のフィードバックを持つことができます。また、EmployeeとPartyの両方が何らかの親オブジェクトに属しているとします。基本的に、我々は持っている:

class User { 
    // Has many 
    Set<Employee> employees; 
    // Has many 
    Set<Organization> organizations; 
    // Has many through employees 
    Set<Organization> associatedOrganizations; 
} 

class Employee { 
    // Belongs to 
    User user; 
    // Belongs to 
    Organization organization; 
    // Has many 
    Set<Feedback> feedbacks; 
} 

class Organization { 
    // Belongs to 
    User user; 
    // Has many 
    Set<Employee> employees; 
    // Has many 
    Set<Party> parties; 
} 

class Party { 
    // Belongs to 
    Organization organization; 
    // Has many 
    Set<Feedback> feedbacks; 
} 

class Feedback { 
    // Belongs to 
    Party party; 
    // Belongs to 
    Employee employee; 
} 

をここで私は、従業員を削除するときになってしまったものです:

// First remove feedbacks related to employee 
Iterator<Feedback> iter = employee.getFeedbacks().iterator(); 
while (iter.hasNext()) { 
    Feedback feedback = iter.next(); 
    iter.remove(); 
    feedback.getParty().getFeedbacks().remove(feedback); 
    session.delete(feedback); 
} 
session.update(employee); 

// Now remove employee from organization 
Organization organization = employee.getOrganization(); 
organization.getEmployees().remove(employee); 
session.update(organization); 

これは、私の定義によって、醜いです。ためには、

Error during managed flush [deleted object would be re-saved by cascade (remove deleted object from associations) 

ので:代わりに私が手

session.delete(employee); 

を:私は

@Cascade({CascadeType.ALL}) 

を使用して、その後、Hibernateは魔法のように単純に実行してすべての関連付けから従業員を削除することを想定しただ​​ろう私のコードを少し洗練されたものにしようとすると(たぶん怠惰なフェッチで十分です、時には私は熱望が必要です)、私はほとんどすべてをフェッチして、私の場合、例えば:

employee.getFeedbacks() 

は、フィードバックは何の問題もなく、いや、すべての切れ目なしにうまく取り込まれ:

failed to lazily initialize a collection of role: ..., could not initialize proxy - no Session 

私が考えた次のことは、オブジェクトのための可能性を取り除いた削除/その関連子供を挿入するが、オブジェクト

child.parent=parent

の代わりに個別にすべてのオブジェクトを挿入する - それはおそらく悪いアイデアのパフォーマンスが賢明だろうバルクでは

parent.children().add(children)となります。

最後に、私は、複数の人が独自のカスタムクエリやものを作成することを推奨していましたが、その時点で、なぜHibernateを気にする必要がありますか?私の問題を比較的きれいに扱う良い方法はないのですか、何かを逃したり、私はばかですか?

+0

一般的に言えば、FETCH JOINを使用していつでも気軽に切り替えることができますが、熱心な負荷を遅延させることはできません。 Hibernateは、見た目よりも扱いにくいです。経験の少ないプログラマーには、「すべてが魔法によって保存されるため、データベースを理解する必要はありません」という驚きがしばしばあります。残念ながら、これは非常に単純な使い方にとどまります。 – Kayaman

+0

しかし、特定のクエリ、注釈だけがない場合、フェッチ結合についてはどうすればよいですか? – Salkz

+0

これは私が言及していた「非常に簡単な使い方」です。特別なクエリを持たない複雑な機能を構築することは期待できません。たとえそれがうまく動作しても、それは絶対に性能を破壊するでしょう。 – Kayaman

答えて

0

私が質問を正しく理解していれば、それはすべて単純な関係を介してカスケード接続することです。1:Nその場合、Hibernateはかなりうまく仕事をすることができます。

​​

コード:

Post post = newPost(); 
doInTransaction(session -> { 
    session.delete(post); 
}); 

を生成します:

delete from Comment where id = 1 
delete from Comment where id = 2 
delete from Post where id = 1 

しかし、あなたは、いくつかの他の(合成)のコレクションを持っている場合、Hibernateはありませんがありますどのようなものかを知る機会があるので、あなたはそれを自分で処理しなければなりません。

Hibernateとカスタムクエリに関しては、Hibernateはよりコンパクトで従来のSQLのHQLを提供しますが、アノテーションよりも透過性が低くなります。

関連する問題