如何及时检测PreparedStatement.setObject()失败?

问题描述 投票:0回答:1

我的程序将一个简单的 CSV 加载到表中。文件中的数据应与表格的布局匹配。

(简化的)代码是:

            String sql = "select * from " + _tableName +
                " where 1 < 0";
            PreparedStatement stmt = _CONN.prepareStatement(sql);
            ResultSet rs = stmt.executeQuery();
            ResultSetMetaData rsmd = rs.getMetaData();
            rs.close();
            stmt.close();

            _columnCount = rsmd.getColumnCount();
            sql = "insert into " + _tableName + " values (" +
                "?,".repeat(_columnCount - 1) + "?)";
            stmt = _CONN.prepareStatement(sql);
...
            int line_no = 0;
readingInput:
            for (String line : Files.readAllLines(input,
                StandardCharsets.UTF_8)) {
                line_no++;
                String[] sa = line.split(_inputSeperator, -1);
                int column = 0;
                for (String st : sa) try {
                    column++; /* JDBC numbers columns from 1... */
                    stmt.setObject(column, st,
                        rsmd.getColumnType(column));
                } catch(SQLException e) {
                    logger.error("{}:{} SQL Exception parsing field {} of <<{}>>",
                        _fileName, line_no, column, line);
                    continue readingInput;
                }
                stmt.addBatch();
            }
...
            stmt.executeBatch();

实际上,这适用于有效输入,但我的一个测试尝试了一条伪造的行——尝试将字符串插入数字列。

此类无效输入确实会产生错误,但仅在最后的

stmt.executeBatch()
行处产生错误,而我对此没有做好准备:
java.sql.BatchUpdateException: Error converting data type nvarchar to int.

当无效值传递到

Statement.setObject()
时,为什么错误不会触发——我的代码准备报告它,跳过虚假输入行并继续?

所有的PreparedStatment.setFoo()方法都被声明为抛出

SQLException
——为什么
setObject()
实际上不抛出一个?

也许这样做是为了节省时间——并且有一些选项可以立即验证传递给PreparedStatement的值,即使需要更长的时间?

jdbc data-binding prepared-statement
1个回答
0
投票

该行为是特定于驱动程序的。一些 JDBC 驱动程序将自行验证转换(因为它们在客户端应用转换,因为服务器需要特定类型),然后您将在调用

setXXX
时遇到异常。其他 JDBC 驱动程序将简单地使用您在
set
上使用的类型的 SQL 等效项将类型化值发送到服务器,并且在执行时,服务器将执行所需的转换,并且如果请求的转换要么成功,要么失败不可能或未满足某些要求。

由于数据库服务器中的功能和行为之间存在巨大差异,因此 JDBC 规范允许两者兼而有之。您无法要求在特定点应用转换。

© www.soinside.com 2019 - 2024. All rights reserved.