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 列。
用于获取subject
、messageId
和from
(或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 同样的错误 - “这是我们之前遇到的一个 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 字段索引减一的主要内容,如果未能解决你的问题,请参考以下文章