クライアントの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 { // … }
      
      





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



All Articles