ResultSet 字段索引减一

Posted

技术标签:

【中文标题】ResultSet 字段索引减一【英文标题】:ResultSet field indices off by one 【发布时间】:2014-01-01 15:03:20 【问题描述】:

我的 SQL:

    String mainSql =
            " SELECT `subject`, `message_id`, `sender`, `date`, `type`, `order`, `body` "
            + " FROM `scan_result` sr LEFT OUTER JOIN `scan_result_body` srb ON `sr`.id = `srb`.scan_result_id "
            + " WHERE `user_id` = ? AND `message_id` = ? "
            + " ORDER BY `type`, `order` ASC ";

我的代码:

    try (PreparedStatement ps = connection.prepareStatement(mainSql)) 
        int idx = 1;
        ps.setInt(idx++, userId);
        ps.setString(idx++, messageId);

        try (ResultSet rs = ps.executeQuery()) 
            boolean firstRow = false;
            while (rs.next()) 
                if (!firstRow) 
                    firstRow = true;
                    builder.setSubject(rs.getString(1));
                    builder.setMessageId(rs.getString(2));
                    builder.setFrom(rs.getString(3));
                    builder.setDate(rs.getDate(4));

我的错误:

...whole 'body' field
</body>
</html>

' can not be represented as java.sql.Date
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1074)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:988)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:974)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:919)
    at com.mysql.jdbc.ResultSetRow.getDateFast(ResultSetRow.java:141)
    at com.mysql.jdbc.BufferRow.getDateFast(BufferRow.java:707)
    at com.mysql.jdbc.ResultSetImpl.getDate(ResultSetImpl.java:2210)
    at com.mysql.jdbc.ResultSetImpl.getDate(ResultSetImpl.java:2172)
    at com.mchange.v2.c3p0.impl.NewProxyResultSet.getDate(NewProxyResultSet.java:3466)
    at me.unroll.bilbo.SQLRunner.getMime(SQLRunner.java:307)

当我在 MySQLWorkbench 中运行 SQL 时,结果行符合预期。 date 是第 4 列。

用于获取subjectmessageIdfrom(或sender)的前三行按预期工作。第四行不知何故跳转到body。这很奇怪。

我正在检查ResultSet。特别是以下字段:

字段[originalTableName=sr,columnName=subject,mysqlType=253(FIELD_TYPE_VAR_STRING)] 字段[originalTableName=sr,columnName=message_id,mysqlType=253(FIELD_TYPE_VAR_STRING)] 字段[originalTableName=sr,columnName=sender,mysqlType=253(FIELD_TYPE_VAR_STRING)] 字段[originalTableName=sr,columnName=date,mysqlType=7(FIELD_TYPE_TIMESTAMP)] 字段[originalTableName=srb,columnName=type,mysqlType=1(FIELD_TYPE_TINY)] 字段[originalTableName=srb,columnName=order,mysqlType=1(FIELD_TYPE_TINY)] 字段[originalTableName=srb,columnName=body,mysqlType=253(FIELD_TYPE_VAR_STRING)]

我简写为我可以确定的相关内容(字段上的命名空间、内存地址和Field 中的不相关字段)。您可以清楚地看到所有 7 个,其中第 4 个是 FIELD_TYPE_TIMESTAMP 的日期,正如我所期望的那样。

ResultSet.get 方法从1 索引。无论如何,这是正确的,并且通过我准确地检索主题和 messageId 的事实得到进一步验证,我可以通过检查 builder 来判断:

<1234567890.JavaMail.app@12345.abcde>
Voted Top 10 Best Magazines By Whoever

(字段省略但可以清楚看到是预期的)。

然而调用rs.getDate(4) 会炸毁一切。为什么?我的下一个调试步骤是逐步完成实现,看看发生了什么,但这对我来说要正确设置有点工作,所以在这里发布。

【问题讨论】:

哦,我对那个流浪角色不好。糟糕! 支持使用构建器模式。时间戳可能不是日期。尝试 java.sql.timestamp 作为时间戳字段。 @DwB 同样的错误 - “ 不能表示为 java.sql.Timestamp” 尝试手动执行查询并检查查询的输出是否符合您的预期。 @DwB 在我的帖子中:“当我在 MySQLWorkbench 中运行 SQL 时,结果行符合预期。日期是第 4 列。” 【参考方案1】:

这是我们之前遇到的一个 MySQL 错误,日期 0000-00-00 会破坏所有内容。一个补丁是在阅读之前将日期0000-00-00 转换为NULL。这是众所周知的,可以通过驱动程序或连接属性来修复。我很肯定有一种更标准的方法可以做到这一点,但这无论如何都可以解决问题:

String url = env.database().url;
char separator = url.contains("?") ? '&' : '?';
url += separator + "zeroDateTimeBehavior=convertToNull";

cpds.setJdbcUrl(url);

见:

https://***.com/a/1180131/1339987

https://***.com/a/2524493/1339987

【讨论】:

以上是关于ResultSet 字段索引减一的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 ResultSet 是不是包含特定命名的字段?

如何检查 ResultSet 中是不是存在字段?

显示 ResultSet 中的自动编号字段时出错

查找 ResultSet 列数? [复制]

ResultSet相关ResultSetMetaData详细

ResultSet转成java类对象