2012-03-13 7 views
6

MySQLデータベースとのインタフェース時に、同じタイプのメソッドをいくつか使用して、別のタイプのパラメータを保存またはロードします。現在、私はそれぞれのタイプごとに異なるメソッドを持っています。これらのメソッドを組み合わせて、異なるタイプをサポートするにはどうすればよいですか?以下同じコードで異なるタイプを使用するリファクタリングメソッド

まだ異なるタイプを使用非常に類似している二つの方法の例である:

public static void saveLongArray(Connection con, int playerID, String tableName, String fieldName, long[] array, long[] originalArray) { 
    try { 
     for (int i = 0; i < array.length; i++) { 
      // Check for change before running query 
      if (array[i] != originalArray[i]) { 
       if (array[i] != 0 && array[i] != -1) { 
        PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)"); 
        updateQuery.setInt(1, playerID); 
        updateQuery.setInt(2, i); 
        updateQuery.setLong(3, array[i]); 
        updateQuery.execute(); 
       } else { 
        PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?"); 
        deleteQuery.setInt(1, playerID); 
        deleteQuery.setInt(2, i); 
        deleteQuery.execute(); 
       } 

       originalArray[i] = array[i]; 
      } 
     } 
    } catch (SQLException ex) { 
     Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving a long array!", ex); 
    } 
} 

public static void saveIntArray(Connection con, int playerID, String tableName, String fieldName, int[] array, int[] originalArray) { 
    try { 
     for (int i = 0; i < array.length; i++) { 
      // Check for change before running query 
      if (array[i] != originalArray[i]) { 
       if (array[i] != 0 && array[i] != -1) { 
        PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)"); 
        updateQuery.setInt(1, playerID); 
        updateQuery.setInt(2, i); 
        updateQuery.setInt(3, array[i]); 
        updateQuery.execute(); 
       } else { 
        PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?"); 
        deleteQuery.setInt(1, playerID); 
        deleteQuery.setInt(2, i); 
        deleteQuery.execute(); 
       } 

       originalArray[i] = array[i]; 
      } 
     } 
    } catch (SQLException ex) { 
     Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving an int array!", ex); 
    } 
} 

なお、実施例ではタイプは、両方の数値です。型が完全に異なる場合(intやStringなど)、重複したメソッドを避けるために何ができますか?

答えて

12

あなたは戦略を適用することができますsetInt()などと設定パラメータの代わりに提供するオブジェクトのtoString()メソッドを使用して、手動で全体のクエリ文字列を生成することができここにパターンこれは彼の質問に答えていません

public static void saveArray<T>(Connection con, int playerID, String tableName, String fieldName, T[] array, T[] originalArray, TypeDependentBehavior<T> behavior) { 
try { 
     for (int i = 0; i < array.length; i++) { 
      // Check for change before running query 
      if (array[i] != originalArray[i]) { 
       if (array[i] != 0 && array[i] != -1) { 
        PreparedStatement updateQuery = con.prepareStatement("REPLACE INTO `" + tableName + "` (`player_id`, `index`, `" + fieldName + "`) VALUES(?, ?, ?)"); 
        updateQuery.setInt(1, playerID); 
        updateQuery.setInt(2, i); 
        behavior.setFieldValue(updateQuery, array[i]); 
        updateQuery.execute(); 
       } else { 
        PreparedStatement deleteQuery = con.prepareStatement("DELETE FROM `" + tableName + "` WHERE `player_id` = ? AND `index` = ?"); 
        deleteQuery.setInt(1, playerID); 
        deleteQuery.setInt(2, i); 
        deleteQuery.execute(); 
       } 

       originalArray[i] = array[i]; 
      } 
     } 
    } catch (SQLException ex) { 
     Logger.getLogger(PlayerSaveHandler.class.getName()).log(Level.SEVERE, "SQL Exception while saving an int array!", ex); 
    } 
} 
+0

私はこのデザインパターンを検討してきましたが、このケースではこれを使用することは考えていませんでした。ありがとうございました! – jSherz

+0

ここで追加するのは、配列はプリミティブの代わりにオブジェクトを保持するので、equals()(例えば '!array [i] .equals(originalArray [i])'または'compareTo()'。また、配列は数値型しか含まれていないと思われるので、Stringの動作は必要なく、type引数はおそらく ''でなければなりません – jpm

+0

インタフェースの実装をJavaで良いアイデアにしていますか?それは抽象クラスとしてはうまくいかないでしょうか? – flurdy

3

int[]の代わりにlong[]を使用します。メモリの相違はです。は、JDBCを使用するコストに比べて小さいです。

Stringを処理する必要がある場合は、オブジェクト型を使用できます。

public static void saveArray(Connection con, int playerID, String tableName, 
    String fieldName, Object[] array, Object[] originalArray) { 

あなたは一般的にすべての配列型にアクセスするためにArray.getLength()Array.get()方法を使用することができますlong[]Object[]のための1つの方法をしたい場合。 これは保存するよりも複雑さを増す可能性があります。

+2

interface TypeDependentBehavior<T> { void setFieldValue(PreparedStatement st, T value); } interface StringBehavior extends TypeDependentBehavior<String> { void setFieldValue(PreparedStatement st, String value) { st.setString(3, value); } } interface IntBehavior extends TypeDependentBehavior<Integer> { void setFieldValue(PreparedStatement st, Integer value) { st.setInt(3, value); } } 

..... "何'場合int'と 'STRING'の?" – ggrigery

2

あなたはそのためにジェネリックを使用することができ、たとえば

void doSomething(int[] array) { 
    for (int i = 0; i < array.length; i++) 
     System.out.println(array[i]); 
} 

void doSomething(long[] array) { 
    for (int i = 0; i < array.length; i++) 
     System.out.println(array[i]); 
} 

<T> void doSomething(T[] array) { 
    for (int i = 0; i < array.length; i++) 
     System.out.println(array[i]); 
} 

に一般化することができ、今、あなたは

int[] array1 = new int[] { 1, 2, 3 }; 
doSomething(array1); 

long[] array2 = new long[] { 1L, 2L, 3L }; 
doSomething(array2); 

String[] array3 = new String[] { "one", "two", "three" }; 
doSomething(array3); 

を呼び出すことができますしかし、あなたはあなたのメソッドの実装を確認する必要がありますし、それがどのアレイタイプ、特にSQLステートメントでも機能することを確認してください。

1

比較機能を突破し、メソッドを最も細かいレベルまで下げた場合はどうなりますか?たとえば、

delete()と同じです。この関数に「新しい」値と「元の」値の両方を渡して内部を比較する理由はありません。配列をループして比較し、必要に応じてupdate()またはdelete()のいずれかを呼び出すことをお勧めします。さまざまなデータ型を扱うために、私はいつもあなたがデータベースで望むもののString値を渡します。同様のタイプで

0

は、あなたがラッパーを作成することができます - 引数int[]として取る方法を、渡された値からlong[]を生成し、実際の作業を実行するために、引数としてlong[]を取る方法バリアントを呼び出します。オーバーヘッドがありますが、配列が何百万ものエントリではないと仮定すると、データベースとの通信コストに比べて無視できます。

完全に異なるタイプの場合、Object[](多分何らかの形でジェネリックを使用する)を試してみることもできますが、いくつかの落とし穴があります。 0または-1の代わりに別の削除マーカーを使用する必要があります(nullは明らかです)。別の方法が呼び出される必要があるので、大きな問題はPreparedStatementにパラメータを設定されていますが、

関連する問題