2012-02-07 14 views
8

私は現在、データベースからデータを取得し、次にUserを作成する次のコードを持っています。このコードは、News,Commentsなどの他のオブジェクトを作成するために私のクラッセの多くで使用されています...Java汎用コンストラクタ

これはApacheのコモンズdbutilsを使用しています。ハンドラがResultSetでジェネリックTをインスタンス化するよう

final ResultSetHandler<User> handler = new ResultSetHandler<User>() { 

      @Override 
      public User handle(ResultSet rs) throws SQLException { 

       User user = null; 
       if (rs.next()) { 
        user = new User(); 
        user.setId(rs.getInt("id")); 
        user.setUsername(rs.getString("username")); 
        user.setPassword(rs.getString("password")); 
       } 
       return user; 
      } 
     }; 

     final User user = run.query(
       "SELECT id, username, password FROM users WHERE username = ? AND active = 2 LIMIT 1;", handler, 
       username); 

は、一般的なクラスにQueryRunnerをラップし、クエリメソッドをオーバーライドすることが可能であろう。私はどのタイプのTでもコンストラクタがResultSetを受け入れることを確かめます。そのよう

 public class QueryExecuter<T> extends QueryRunner { 
    private ResultSetHandler<T> _handler; 

    public QueryExecuter(){//The T type was for testing haha 
     super(); 
     handler = new ResultSetHandler<T>() { 

      @Override 
      public T handle(ResultSet rs) throws SQLException { 

       T object = null; 
       if (rs.next()) { 
        object = new T(rs); 
       } 
       return object; 
      } 
     }; 
    } 
} 

あなたが理解してよかどうかは知りませんが、私はそう願って、あなたがより多くの詳細や、より良い説明をしたい場合は私に尋ねます。

EDIT

私は貴様のオブジェクトのすべてが伸びるだろうと代わりにジェネリック型のAbstractClassを使用することができると思ったが、私は抽象的なコンストラクタを書くことができないように思えます。私はJavaでこれを行うことが可能であるとは思わない

public abstract class DatabaseEntity { 
    public static abstract DatabaseEntity create(ResultSet rs);//even this doesn't work... 
} 
+0

なぜ、コンストラクタに 'T type'を渡す必要がありますか? – yair

+0

リフレクションを使用すると、結果セットを持つクラスコンストラクタを呼び出すことができます –

答えて

8

可、はい?しかし、それは悪い考えです。あなたが行うことができ

class ResultSetHandler<T> { 
    ResultSetHandler<T>(Class<T> clazz) { 
    this.clazz = clazz; 
    } 

    public T handle(ResultSet rs) throws SQLException { 
    T object = null; 
    if (rs.next()) { 
     object = clazz.getConstructor(ResultSet.class).newInstance(rs) 
    } 
    return object; 
    } 
} 

ドメインやデータベースをミキシングは、しかし、悪い考えです。良いだろう何、しかし、結果セットに基づいてオブジェクトを作成しますabtract方法を定義することです:あなた実装するクラスでは、

abstract class ResultSetHandler<T> { 

    protected abstract T create(ResultSet rs); 

    public T handle(ResultSet rs) throws SQLException { 
    T object = null; 
    if (rs.next()) { 
     object = create(rs); 
    } 
    return object; 
    } 
} 

その後に、あなただけの結果を処理するのではなく、create()方法を提供する必要があります

h = new ResultSetHandler<Person>() { 
    protected Person create(ResultSet rs) { 
    return new Person(rs.getString("name")); 
    } 
} 
+0

+1と同じ答えを提供しますが、良いコード例があります。 –

+0

あなたは、ドメインとデータベースを混在させることは良い考えではないと私はそれを得るが、あなたはクエリ結果からこれらのオブジェクトを構築すると思いますか? – David

+0

私はMVCアーキテクチャを使用していますので、私のモデルは永続性のためにあり、データベースに自身を保存して更新する方法を知っていますが、ユーティリティを使用してデータベースに対してクエリを実行します。多分DAOを使用しますか? – David

0

:私は次のようにオブジェクトのインスタンスを返す静的メソッドを作成する必要があります。総称でTのインスタンスを作成することはできません。 JavaのGenericsはC++のような実際のテンプレートではなく、キャストを取り除いてコンパイル時の警告を引き起こすobjectのまわりの構文砂糖だけです。

Tにはコンストラクタが必要なようにC#で制約がありません。

リフレクションを使用して適切なクラスを解決するのが最善の策ですが、メソッドが呼び出されるときにTのランタイムクラスを知ることができないため、問題が発生します。この情報はjavaバイトコードしたがって、リフレクションを使用するには、クラスをメソッドに渡す必要があります。とにかく、これは良いデザインアイデアだとはっきりしていません。

+0

JB Nizetと同じように、リフレクションを行うことができます。 –

+0

確かに可能です。 'Class 'への参照が必要です。 –

+0

はい、反射します。あなたはまだ実際のクラスをメソッドに渡す必要があります。クラス情報が実行時に存在していれば、T.classを実行することはできません。 – Dervall

3

あなたはオブジェクトのクラスを渡してコンストラクタを呼び出すために使うことができますが、POJOをJDBCに依存させることは難しいでしょう。データベースに格納されますが、読み込むために使用されたエイリアスも使用されています。

つまり、外部の未知のクエリの結果セットを処理するのは、ユーザーPOJOコンストラクタの責任ではありません。

あなただけ

if (rs.next()) { 

ブロックを持っているでしょうし、抽象メソッドに実際のエンティティの作成を委任するだろうが、あなたはあまり得られないでしょうAbstractSingleEntityHandlerのスーパークラスを設計することができます。

+0

+1私より速く、私が望んでいたものを正確に書くために+1); –

+0

上記のハンドラ本体が最初のコードブロックで表示され、オブジェクトのすべてのクエリで繰り返されるため、これを実行しようとしています。私はdbから来る私のオブジェクトが 'query'メソッドが直接オブジェクトを返すクエリー結果から自分自身を構築する方法を知っていることを確認することがうれしいと思いました。 – David

+0

POJOとはどういう意味ですか? – David

関連する問題