2012-04-12 6 views
2

Javaの既存のコードを修正しようとしています(私が行ったことがない)、prepare文を使用していないクエリが見つかりました。 私はたくさんのコードを持っているので、できるだけ少なく修正しようとしています。 は、だからではなく、私はそのような何かをしたいと思いますprepare文:パラメータのArrayListを使用したメソッドの作成

public void executeInsertStmt(String strQuery, String param1, String param2) { 

... 
... 
PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest); 
preparedStatement.setString(1, param1); 
preparedStatement.setString(2, param2); 
} 

ようなメソッドを持っていることの(私はそれが最善の解決策であるかわかりません)。

public void executeInsertStmt(String strQuery, ArrayList<ArrayList<Object>> parameters) { 

PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest); 

int counter=1; 
      for (final ArrayList<Object> eachParam : parameters) { 

       switch(DataTypes.valueOf(eachParam.get(0).toString().toUpperCase())) 
       { 
        case STRING: 
         preparedStatement.setString(counter, (String)eachParam.get(1)); 
        break; 
        case DATE: 
         preparedStatement.setDate(counter, (Date)eachParam.get(1)); 
        break; 
        case INT: 
         preparedStatement.setInt(counter, (Integer)eachParam.get(1)); 
        break; 
        default: 
         preparedStatement.setString(counter, (String)eachParam.get(1)); 
        break; 
       } 

       counter++; 

      } 
} 

そして、このような何か持っている:私は、パラメータの数が異なる多くのクエリを持っているので

strQuery = "insert into toto values (?,?)"; 
ArrayList<Object> paramToPass1 = new ArrayList<Object>(); 

paramToPass1.add("String"); 
paramToPass1.add("TheValueForTheString"); 

ArrayList<Object> paramToPass2 = new ArrayList<Object>(); 

paramToPass2.add("String"); 
paramToPass2.add("TheValueForTheString2"); 

ArrayList<ArrayList<Object>> paramToPass = new ArrayList<ArrayList<Object>>(); 

paramToPass.add(paramToPass1); 
paramToPass.add(paramToPass2); 


executeInsertStmt(strQuery,paramToPass); 

をaproach、この種のは、私にとって最高になります。 私は各タイプのクエリに対してメソッドを実行する必要はありません。

あなたはどう思いますか?

何か問題はありますか? 最善の方法はありますか?

ありがとうございます。

+0

私は何か類似していましたが、2つのメソッド、1つは 'List lstParameters'を受け取り、もう1つは' List lstParameters'で、1番目はINパラメータを持つ配列を受け取りました.2番目は 'MyOwnSQLParatemer'オブジェクトを受け取りました。パラメータの方向を指示します:IN、OUT、INOUT。 –

+0

Spring JDBCを使用することが許可されていれば、これは大幅に単純化されます。 – GriffeyDog

+0

とにかく多くの作業を進めているなら、徐々に上位レベルのソリューションに移行してください。[jOOQ](http://www.jooq.org)、[DbUtils](http:// commons。 apache.org/dbutils/)、[spring-data](http://www.springsource.org/spring-data)、[Hibernate](http://www.hibernate.org/)などがあります。 –

答えて

1

ArrayList<Object>(サイズ2)ではなく、パラメータとしてオブジェクト表現を使用する必要があります。また、独自のDataType列挙は必要ありません。既にjava.sql.Typesクラスがあります。これらの型の値を認識するPreparedStatementにはsetObject()メソッドがあるので、switchステートメントや型固有のメソッドPreparedStatement.set..()を呼び出す必要はありません。

ここでは、パラメータのオブジェクト表現を持つソリューションがあり、これらのタイプのサポートとしてjava.sql.TypespreparedStatement.setObject()の利点を利用し、型定数値から隔離します。

まず、パラメータのためのオブジェクト表現:

import java.sql.Types; 

public class ParamDescriptor { 
    // Constructor itself is private, we are encapsulating so that 
    // you don't need to write java.sql.Types constants yourself 
    private ParamDescriptor(int dataType, Object value) { 
     _dataType = dataType; 
     _value = value; 
    } 

    // Factory methods for actual instantiation 
    public static ParamDescriptor forInt (int paramVal) { 
     return new ParamDescriptor (Types.INTEGER, paramVal); 
    } 

    public static ParamDescriptor forString (String paramVal) { 
     return new ParamDescriptor (Types.VARCHAR, paramVal); 
    } 

    public static ParamDescriptor forDate (Date paramVal) { 
     return new ParamDescriptor (Types.DATE, paramVal); 
    } 
    // Add more here to support more data types . . . .  


    public int getDataType() { 
     return _dataType; 
    } 

    public Object getValue() { 
     return _value; 
    } 

    private int  _dataType; 
    private Object _value; 
} 

次に、executeInsertStmt()の新バージョン。私たちは、わずか数行にそれを削減しました、そして、それは関係なく、パラメータの型のための将来のサポートの、再び変更する必要はありません:最後に

public void executeInsertStmt(String strQuery, List<ParamDescriptor> parameters) throws SQLException {  
     PreparedStatement preparedStatement = cnx.prepareStatement(strQuery); 

     int counter = 1; 
     for (ParamDescriptor paramDescriptor : parameters) { 
      preparedStatement.setObject(counter, 
             paramDescriptor.getValue(), 
             paramDescriptor.getDataType()); 
      counter++; 
     } 
    } 

、新しいexecuteInsertStmt()を呼ぶだろうコード:

String strQuery = "insert into toto values (?,?)"; 

ParamDescriptor paramToPass1 = ParamDescriptor.forString("TheValueForTheString"); 
ParamDescriptor paramToPass2 = ParamDescriptor.forString("TheValueForTheString2"); 

List<ParamDescriptor> parameters = new ArrayList<ParamDescriptor>(); 
parameters.add(paramToPass1); 
parameters.add(paramToPass2); 

executeInsertStmt(strQuery, parameters); 

小数点の取り扱いを計画している場合、小数点以下の桁数を指定できる別のバージョンのPreparedStatement.setObject()があることに注意してください。 executeInsertStmt()に何らかのサポートを追加する必要があります。

+0

素晴らしい。どうもありがとう。あなたの方法ははるかにクリーンです。私を助けてくれる –

+0

私の喜び!喜んで助けてください。賛辞と受け入れをありがとう。 –

0

あなたのアイデアは悪くないです...ちょっとしたポインタです。

ArrayListのArrayListを渡さないでください。むしろinstanceofまたはDataHolderクラスを使用してください。

方法1:

シンプルがタイプ整数、文字列、ダブルなどを追加して、あなたの方法でのinstanceof:

public void executeInsertStmt(String strQuery, ArrayList<Object> parameters) { 

    PreparedStatement preparedStatement = cnx.prepareStatement(stringRequest); 
    int counter=1; 
    for (final Object eachParam : parameters) { 
     if (eachParam instanceof String) { 
      preparedStatement.setString(counter, (String)eachParam); 
     } else if (eachParam instanceof Integer) { 
      preparedStatement.setInt(counter, (Integer)eachParam); 
     } else ... 

     counter++; 

    } 
} 

DataHolderとの考え方は一つのフィールドの型を保つことであるともう1つは実際のデータです。ジェネリックを使いこなすことさえできます。しかし、私はこのケースではinstanceofのために行くだろう。

+1

これは 'Date'データ型を除いて良いことがあります、' setDate'、 'setTime'、' setTimestamp'メソッドがあります –

+0

ありがとう答えのために。私はちょっと疑問を持っています:DataHolderとは何ですか?私はjdkでそれを見ない?それはカスタムフレームワークですか? –

+0

ArrayListでのArrayListの使用を避けるために書く必要のある独自のクラスです。何かが好きです:class DataHolder {Type type;オブジェクトデータ。 }この場合、Typeはenumでもかまいません(ただし、元々はStringのように動作します) –

関連する問題