2017-11-26 1 views
2

私はここで何かが分かりませんか?java.sqlite setObjectがPreparedStatementに設定されていません

org.xerial:sqlite-jdbc:3.21.0を使用してSQLiteローカルデータベースに対してクエリを実行する方法は次のとおりです。私は、次の値と一緒にメソッドに次のSQLを渡すとき

public List<HashMap<String, Object>> executeQuery(String sql, List<Object> vals) throws Exception { 
    List<HashMap<String, Object>> rows = new ArrayList<>(); 
    Connection conn = getConnection(); 
    try (PreparedStatement stmnt = conn.prepareStatement(sql)) { 
     if (!vals.isEmpty()) { 
      for (int i = 0; i < vals.size(); i++) { 
       stmnt.setObject(i + 1, vals.get(i)); 
      } 
     } 
     ResultSet rs = stmnt.executeQuery(); 
     ResultSetMetaData meta = rs.getMetaData(); 
     HashMap<String, Object> row; 
     while (rs.next()) { 
      row = new HashMap<>(); 
      for (int i = 0; i < meta.getColumnCount(); i++) { 
       row.put(meta.getColumnName(i + 1), rs.getObject(i + 1)); 
      } 
      rows.add(row); 
     } 
    } finally { 
     putConnection(conn); 
    } 
    return rows; 
} 

しかし、彼らは設定されません(それはまた、例外をスローしません)。それは内部的にそれを割り当てているようですが、データベースに伝えるのは忘れてしまいます。

SELECT * FROM 'airlines' WHERE 'name' LIKE ? LIMIT 1 

vals: size = 1 {"MyAirline"} 

私はデバッグからループ内に入ってsetObjectになることがわかります。 ANSI標準のSQLでは

enter image description here

答えて

2

、単一引用符(')はリテラル文字列と二重引用符(")を区切るために使用されているテーブル/カラム名を区切るために使用されています。だから、

SELECT * FROM 'airlines' WHERE 'name' LIKE ? LIMIT 1 

は本当に「文字列リテラルの 『name』のパラメータによって提供されるパターンにマッチした文字列リテラル「航空会社からのすべての列を選択する」を意味します。

興味深いことに、SQLiteはテーブル名「航空会社」として文字列リテラル「航空会社」を解釈してくれのようですが、それはまだ文字列リテラルとしての「name」に解釈されます。したがって、 "airlines"のすべての行について、リテラル文字列 'name'を文字列値 'MyAirline'と比較しています。一致しないため、結果セットには行が含まれません。

あなたのSQLコマンドテキストが

SELECT * FROM "airlines" WHERE "name" LIKE ? LIMIT 1 

する必要がありますので、SQLiteは値を持つ「名前」欄の内容を比較します「MyAirline」。

+0

Owwwwwwwww! :)ファンタスティック、それは今働いている。どうもありがとう。 – Christian

関連する問題