0

SQLクエリを受け取って実行するdb SELECTステートメントをラップするメソッドを書いています。結果は に収集されObject[][]ます。データベース内のすべてのセルは整数または文字列です。

戻り配列に問題があります。ですObject[][]のでゆるいタイプです。

public Object[][] select(String query) {
    Object[][] result = new Object[cursor.getCount()][cursor.getColumnCount()];
    Cursor cursor = db.rawQuery(query, null);

    //Iterate over cursor (rows)
    do {
        //Iterate over columns (cells with data of different type)
        for(int columnIndex = 0; columnIndex < cursor.getColumnCount(); columnIndex++) {
            int type = cursor.getType(columnIndex);

            //assume, that there are only two types - String or Integer (actualy there are 3 more types)
            if(type == Cursor.FIELD_TYPE_INTEGER) {
                result[cursor.getPosition()][columnIndex] = cursor.getInt(columnIndex);
            }
            else if(type == Cursor.FIELD_TYPE_STRING) {
                result[cursor.getPosition()][columnIndex] = cursor.getString(columnIndex);
            }
        }
    } while (cursor.moveToNext());

    return result;
}

ゆるくしたくないタイプ。たとえば、次のようにできるようにしたい (疑似コード):

//pseudocode:
result = select("SELECT age, name FROM people")
print( "Hello, " + result[0][0] + ". In ten years you'll be " )
print( result[0][0] + 10 )
//Prints: Hello, John. In ten years you'll be 56

Java に関するすべての本には、さまざまな型の配列を持つことはできないと書かれています。それは明確だ。

しかし、DB からこのすべての整数と文字列を保持するにはどうすればよいでしょうか? コレクションとジェネリックを使用しようとしましたが、うまくいきませんでした - Java は初めてです。

また、ある種の Result 値ホルダーを使用しようとしました:

private class Result {
    private Class type;
    private Object value;

        ...

    public ??? get() { //??? - int or string - here I have some problems :)
        return this.type.cast(this.value);
    }

    //do NOT want to have these:
    public int getInt() { return (int) value; }
    public int getString() { return (String) value; }
}

この場合、メソッドselect(...)は戻ります。Result[][]

自問自答: PHP で行ったように、Java でコーディングしようとしていたことを理解しました。強い型付けでは、明示的なキャストなしですべての型を返す、単純な方法を作成できません。

結局、共通のデータ オブジェクトを作成し、選択時にそれらを埋めることにしました。

4

5 に答える 5

3

必要なものをラップしてインスタンス化する Result クラスを作成しないのはなぜですか?

于 2012-08-08T19:16:39.930 に答える
2

私はおそらく次のようなことをするでしょう...

public final class Row {

  private final Map<String, ?> columns;

  protected Row(final Map<String, ?> columns) {
    this.columns = columns;
  }

  public <T> T get(final String name) {
    return (T) columns.get(name);
  }  

  public <T> T get(final String name, final Class<T> type) {
    return (T) columns.get(name);
  }
}

public final Iterable<Row> select(final String query) {
  final Cursor cursor = db.rawQuery(query, null);
  final int numRow = cursor.getCount();
  final int numCol = cursor.getColumnCount();
  final Row[] rows = new Row[numRow];
  for (int row = 0; row < numRow; ++row) {
    final Map<String, Object> cols = new HashMap<String, Object>(numCol);
    for (int col = 0; col < numCol; ++col) {
      final String name = cursor.getColumnName(col);
      final Object val = null;
      final int type = cursor.getType(col);
      switch (type) {
        case Cursor.FIELD_TYPE_INTEGER:
          val = cursor.getInt(col);
          break;
        case Cursor.FIELD_TYPE_STRING:
          val = cursor.getString(col);
          break;
        ...
      }
      map.put(name, val);
    }
    rows[row] = new Row(cols);
    cursor.moveToNext();
  }
  return Arrays.asList(rows); 
}

private final Row selectFirst(final String query) {
  return select(query).iterator().next();
}

に続く...

final Row result = selectFirst("SELECT age, name FROM people");
print("Hello, " + result.get("name") + ". In ten years you'll be "
          + (result.<Integer>get("age") + 10)).

... または、同等に:

final Row result = selectFirst("SELECT age, name FROM people");
final String name = result.get("name");
final int age = result.get("age");
print("Hello, " + name + ". In ten years you'll be " + (age + 10));

変数を使用すると、javacはそれぞれget(StringおよびInteger) の型パラメーターを推測できます。

returnであるため、ループで使用できselectます。Iterable<Row>for

for (final Row row : select(...)) {
  /* operate on the row */
}

これが1つか2つの微調整なしでコンパイルされるかどうかはわかりません。申し訳ありませんが、テストしていませんが、一般的な考え方はすべきです。

于 2012-08-08T20:07:26.080 に答える
1

最善の方法は、データベースから取得するプロパティを使用して getter/setter を使用して Java Bean を作成することです。たとえば、従業員を取得している場合

class Employee
{
int empID;
String empName;

public void setEmpID(String eID)
{
empID= eID;
}

public int getEmpID()
{
return eID;
}
.......
}
于 2012-08-08T19:15:39.123 に答える
0

使うMap<String,List<Result>>

Result クラスは、実際の値とその型を格納できます

class Result {

   Object value;
   DataType type;

}

enum DataType {

  String,
  Integer

}
于 2012-08-08T19:23:42.457 に答える
0

次のように、列名またはインデックスをキーとしてマップのリストを返します。

public List<Map<Integer,Result>> select(String query)

データを抽出するときは、次のようにします。

List<Map<Integer,Result>> data = new ArrayList<Map<Integer,Result>>();
...
Map<String,Result> elem = new...
elem.put(columnIndex, new Result(..));

data.add(elem);

コレクションは、配列よりも確実に強力です。

編集Result提供したホルダークラスを 使用しました。

于 2012-08-08T19:19:22.147 に答える