java - Java 中的PreparedStatement 问题针对Oracle

标签 java oracle prepared-statement

出于安全和性能原因,我正在修改一些代码以使用准备好的语句而不是普通的语句。

我们的应用程序当前正在将信息存储到嵌入式 derby 数据库中,但我们很快就会转向 Oracle。

关于 Oracle 和准备好的语句,我发现了两件事需要你们的帮助:

1- 我找到了 this document说 Oracle 不处理将参数绑定(bind)到 IN 子句中,因此我们无法提供如下查询:

Select pokemon from pokemonTable where capacity in (?,?,?,?)

这是真的吗?有什么解决方法吗? ... 为什么 ?

2- 我们有一些 TIMESTAMP 类型的字段。因此,对于我们的实际语句,查询如下所示:

Select raichu from pokemonTable where evolution = TO_TIMESTAMP('2500-12-31 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF')

准备好的声明应该做什么?我应该将其放入参数数组中吗: 2500-12-31 或 TO_TIMESTAMP('2500-12-31 00:00:00.000', 'YYYY-MM-DD HH24:MI:SS.FF') ?

感谢您的帮助,希望我的问题得到解答!

问候,

最佳答案

看到这份文件我有点惊讶。确实,您不能像下面这样设置数组/集合(这与使用的数据库/JDBC 驱动程序无关):

String sql = "SELECT col FROM tbl WHERE id IN (?)";
statement = connection.prepareStatement(sql);
statement.setArray(1, arrayOfValues); // Fail.

但是文档中提到的查询应该可以工作。我可以从至少 Oracle 10g XE 与 ojdbc14.jar 结合使用的经验中看出这一点。我怀疑该文档的作者混淆了一些内容,或者它实际上涉及不同(较旧的?)版本的 DB 和/或 JDBC 驱动程序。

无论使用什么 JDBC 驱动程序,以下内容都应该有效(尽管您依赖于使用的数据库 IN 子句可以包含多少项,Oracle(是的,再次)有大约 1000 项的限制):

private static final String SQL_FIND = "SELECT id, name, value FROM data WHERE id IN (%s)";

public List<Data> find(Set<Long> ids) throws SQLException {
    Connection connection = null;
    PreparedStatement statement = null;
    ResultSet resultSet = null;
    List<Data> list = new ArrayList<Data>();
    String sql = String.format(SQL_FIND, preparePlaceHolders(ids.size()));

    try{
        connection = database.getConnection();
        statement = connection.prepareStatement(sql);
        setValues(statement, ids.toArray());
        resultSet = statement.executeQuery();
        while (resultSet.next()) {
            Data data = new Data();
            data.setId(resultSet.getLong("id"));
            data.setName(resultSet.getString("name"));
            data.setValue(resultSet.getInt("value"));
            list.add(data);
        }
    } finally {
        close(connection, statement, resultSet);
    }

    return list;
}

public static String preparePlaceHolders(int length) {
    StringBuilder builder = new StringBuilder();
    for (int i = 0; i < length;) {
        builder.append("?");
        if (++i < length) {
            builder.append(",");
        }
    }
    return builder.toString();
}

public static void setValues(PreparedStatement preparedStatement, Object... values) throws SQLException {
    for (int i = 0; i < values.length; i++) {
        preparedStatement.setObject(i + 1, values[i]);
    }
}

关于TIMESTAMP问题,只需使用PreparedStatement#setTimestamp() .

关于java - Java 中的PreparedStatement 问题针对Oracle,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2510083/

相关文章:

database - 如何使用较旧的日期字段删除 SQL 中的重复行

oracle - 将 "WM_CONCAT(col)"定义为 "LISTAGG(col, ' ,')"用于 Oracle 迁移

Oracle关于集合和顺序的表表达式

php - 使用准备好的语句将 MySQL SELECT 结果存储在 php 变量中

php - native 准备语句 : are they so limited?

java - 将 LocalTime 传递给PreparedStatement

java - 不是 Vectors java 类的实例

java - 记录 Maven 原型(prototype)以及项目布局和使用情况

java - 有什么方法可以在 cassandra 中实现无状态分页吗?

java - Android Firebase - 如何将 DatabaseReference 设置为为所有用户生成的推送 key ?