2017-12-24 21 views
0

現在、ORMを使用せずに単純なJava Webアプリケーションを開発中です。カスタムORMで遅延ロードする

レイヤードアーキテクチャです。私は注釈を使用して、ドメインクラスのカラムをリポジトリがあるパーシスタンスレイヤにマップします。

私のDefaultRepositoryは、リフレクションを使用してフィールド名を取得し、クエリを作成しています。私はちょうど各ドメイン(ユーザー、注文、製品など)ごとに別のものを作る代わりに、この1つを使用します。

それは次のようになります。

リポジトリ:

public abstract class DefaultRepository <TYPE extends DefaultDomain<TYPE>>{ 

    public int insert(Connection con, TYPE entity){}; 
    public int update (Connection con, TYPE entity){}; 
    public int delete (Connection con, TYPE entity){}; 
    public int findById(Connection con, int id){}; 
    ... 

} 

私が要求された場合にのみ、各ユーザの注文をロードするために遅延ロードを実装したいです。これは、好ましくは、結果セットを私のTYPE(ドメインクラス)にマップするfindById()のリポジトリで発生します。

私はこの外部キーの関係を、一般的には1対多対多対多に実装する方法はありますか?

考えられるのは、特定のリポジトリを使用して注釈を作成し、その後、オーダーリストが呼び出されたときにfindAll()メソッドを呼び出すことでした。例えば

public class Order extends DefaultDomain{ 
    @ManyToOne(repository=UserRepository.class) 
    private User user; 

} 

は正しい方法ということですか?これには異なる/より良いアプローチがありますか?

+2

あなたはORMを使用しています。自分で書くことを選択しています。あなたが書いたアノテーションは、JPAが使用する注釈です。 – duffymo

+0

ありがとう、私はそれを貧弱に言いました。私はJPA/Hibernateがどのようにこれをやっているのか調べてみましたが、コードワイズなものは見つけられませんでした。 – user9136913

+0

あなたは @ManyToOne(= FetchType.LAZYをフェッチ) – Mazen

答えて

-1

私はこの場合、私はProxy Design PatternCGLibを組み合わせて使用​​しました。

基本的には、ORMの永続オブジェクトを返すプロキシを生成するファクトリを使用してオブジェクトをインスタンス化し、管理するメソッドをリッスンするリスナーを自動的に作成します。 私はこれがあなたを助けてくれることを願っています。

https://docs.oracle.com/javase/7/docs/api/java/lang/reflect/Proxy.html

public interface PersonInterface{ 
    public String getName(); 
    public void setName(String name); 
    public int findById(int id); 
} 
public static class Person implements PersonInterface{ 

    String name; 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    @Override 
    public int findById(int id) { 
     return id; 
    } 
} 
public static class ProxyPersonImpl implements java.lang.reflect.InvocationHandler{ 

    private PersonInterface person; 

    public ProxyPersonImpl(Person person) { 
     this.person = person; 
    } 
    public static PersonInterface newInstance(Person obj) { 
     return (PersonInterface) java.lang.reflect.Proxy.newProxyInstance(
      obj.getClass().getClassLoader(), 
      obj.getClass().getInterfaces(), 
      new ProxyPersonImpl(obj)); 
    }  
    @Override 
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { 
     System.out.println("My Proxy listen this method invocation:"+method.getName()); 
     return method.invoke(person, args); 
    } 
} 

public class ProxyTest { 
    public static void main(String[] args) { 
     PersonInterface p = ProxyPersonImpl.newInstance(new Person()); 
     p.setName("Name seted"); 
     String name = p.getName(); 
     System.out.println(name); 
     int i = p.findById(1); 
     System.out.println(i); 
    } 
} 
class Repository { 
    Connection con; 
    public Repository() { 
     con = ConnectionFactory.getConnection(); 
    } 

    public Person findById(int id) { 
     Person p = new Person(); 
     try { 
      PreparedStatement statement = con.prepareStatement("Your sql here"); 
      ResultSet result = statement.executeQuery();     
      if(result.next()) { 
       p.setName(result.getString("Name")); 
      }   
     } catch (SQLException e) { 
      // TODO Auto-generated catch block 
      e.printStackTrace(); 
     } 

     return p; 
    }  
} 

static class ConnectionFactory { 
    private static Connection con; 

    public static Connection getConnection() { 
     if(con == null) { 
      //create connection here 

     } 
     return con; 
    }  
} 
+0

ありがとう、私は本当にこのパターン私を助けるつもりです。私はすでにメソッドを取得する方法を知っていて、 "デフォルト"のリポジトリを作成したくない場合は問題にならず、代わりに各ドメインのリポジトリを作成します。 – user9136913

+0

私は解明する答えを編集しました。メソッドが呼び出されたときに、メソッド呼び出しのリスナーが必要な場合は、データベースからデータをロードするなどの決定を下すことができます。これを行うには、永続オブジェクトの処理方法を変更する必要があります。 –

+0

私はあなたのアノテーションを改善するかもしれないと思う、@ManyToOne(repository = UserRepository.class、lazy = true) –