【问题标题】:java.sqlite setObject not setting on PreparedStatementjava.sqlite setObject 未在 PreparedStatement 上设置
【发布时间】:2017-11-26 13:46:32
【问题描述】:

我在这里遗漏了什么明显的东西吗?

我有以下方法可以使用org.xerial:sqlite-jdbc:3.21.0 对 SQLite 本地数据库执行查询。

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;
}

但是,当我将以下 SQL 连同以下值一起传递给方法时,它们不会被设置(但它也不会引发异常)。这就像它在内部分配它但忘记告诉数据库一样。

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

vals: size = 1 {"MyAirline"}

我可以从调试中看到它进入了循环到setObject

【问题讨论】:

    标签: java sql sqlite jdbc


    【解决方案1】:

    在 ANSI 标准 SQL 中,单引号 (') 用于分隔文字字符串,双引号 (") 用于分隔表/列名称。所以

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

    真正的意思是“从文字字符串'airlines'中选择所有列,其中文字字符串'name'与参数提供的模式匹配”。

    有趣的是,SQLite 似乎足够聪明,可以将 文字字符串 'airlines' 解释为 表名 “airlines”,但它仍然将 'name' 解释为文字字符串。因此,对于 "airlines" 中的每一行,它会将文字字符串 'name' 与字符串值 'MyAirline' 进行比较,并且永远不会匹配,因此 ResultSet 不包含任何行。

    你的 SQL 命令文本应该是

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

    因此 SQLite 会将“名称”列的内容与值“MyAirline”进行比较。

    【讨论】:

    • 哇哇哇!! :) 太棒了,它现在正在工作。非常感谢。
    猜你喜欢
    • 1970-01-01
    • 2016-02-13
    • 1970-01-01
    • 1970-01-01
    • 2016-11-15
    • 1970-01-01
    • 1970-01-01
    • 2017-07-11
    • 1970-01-01
    相关资源
    最近更新 更多