クライアントのJPAエンティティをプロキシする方法(遅延初期化との闘い)

最近、Hibernateでのレイジー初期化との戦いに関するHabrの投稿を見たとき、私は興味を持ちました-私は投稿自体を読み、コメントが追加されるまで待ちました-誰もこの問題を解決する方法を提案しますか? 私はそのようなものを見ませんでした。 カットの下の方法。

例で説明します。 エンティティがあるとしましょう:
@Entity public class Person { @Id private long id; private String firstName; private String lastName; @OneToMany private List<Person> children; // getters-setters } 

このエンティティの表現がクライアントに送信されたときに、子リストが初期化され、さらにHibernateガーターをプルしないようにする必要があります。 これを行うには、次のインターフェイスを宣言します。
 public interface IPerson { public long getId(); public void setId(long id); // getters-setters for firstName/lastName public List<IPerson> getChildren(); public void setChildren(List<IPerson> children); } 

クライアントに送信されるのはこのビューです。 PersonはIPersonを実装しないことに注意してください。 また、クライアントはPersonの存在についてまったく知りません。 彼にとって、インターフェースという形での彼のさまざまな表現しかありません。 プロキシは次のようになります。
 Person examplePerson = getPersonFromDb(); IPerson personProxy = ProxyFactory.getProxy(IPerson.class, examplePerson); 

どのように機能しますか? ProxyFactory.getProxy()メソッドは、動的プロキシメカニズムを使用して、IPersonインターフェイスの実装を作成します。このハンドラーには、フィールド値を持つMapがあります。 このマップを埋めるために、ProxyFactoryはエンティティフィールドexamplePersonのリフレクションを読み取ります。 したがって、インターフェイスでゲッター/セッターが呼び出されると、ハンドラーはこのマップに忍び込みます。

当然、エンティティには複数のインターフェイスを含めることができ、プロキシにはフィールドの一部のみを含めることができます。 リストの例(リスト<IPerson>の例)の場合、リストを構成するプロキシを指定することもできます(たとえば、リスト<IPersonOnlyWithName>)。

コンパイル段階でプロキシインターフェイス(インターフェイスが実際にエンティティに対応していること)をチェックするために、次のように注釈が付けられたエンティティを通過する単純なAntビルダーがEclipse用に作成されました。
 @Entity @ProxyBinding(interfaceClass = IPerson.class) public class Person { // … } 

このアプローチは、実際にその実行可能性を証明し、さまざまな追加を獲得しました。 建設的な批判やコメントを見るのは面白いでしょう。


Source: https://habr.com/ru/post/J112621/


All Articles