在 SQLite 中使用 DATETIME 列时如何避免 NumberFormatException?
Posted
技术标签:
【中文标题】在 SQLite 中使用 DATETIME 列时如何避免 NumberFormatException?【英文标题】:How to avoid the NumberFormatException when using a DATETIME column in SQLite? 【发布时间】:2019-10-17 14:42:14 【问题描述】:我正在使用带有包含 DATETIME 列的表的 SQLite 数据库。 jOOQ 默认将 DATETIME 列绑定到 java.sql.Timestamp。查询具有 DATETIME 列的表会导致每列出现 NumberFormatException(已处理)。
我正在使用 jOOQ 3.11.9。
org.jooq.impl.DefaultBinding.DefaultTimestampBinding
parse 方法首次尝试将时间戳字符串值转换为数字时抛出异常。
private static final long parse(Class < ? extends java.util.Date > type, String date) throws SQLException
// Try reading a plain number first
try
return Long.valueOf(date);
// If that fails, try reading a formatted date
catch (NumberFormatException e)
// [#7325] In SQLite dates could be stored in both ISO standard formats:
// With T (default standard), or without T (optional standard, JDBC standard)
date = StringUtils.replace(date, "T", " ");
if (type == Timestamp.class)
return Timestamp.valueOf(date).getTime();
// Dates may come with " 00:00:00". This is safely trimming time information
else if (type == Date.class)
return Date.valueOf(date.split(" ")[0]).getTime();
else if (type == Time.class)
return Time.valueOf(date).getTime();
throw new SQLException("Could not parse date " + date, e);
查看get0
和set0
DefaultTimestampBinding 方法,时间戳总是作为字符串获取/设置。 SQLite 是否有理由不将其作为时间戳传递给 JDBC 语句/结果?有没有办法覆盖这种行为或避免异常?
Override
final void set0(BindingSetStatementContext < U > ctx, Timestamp value) throws SQLException
if (ctx.family() == SQLITE)
ctx.statement().setString(ctx.index(), value.toString());
else
ctx.statement().setTimestamp(ctx.index(), value);
@Override
final Timestamp get0(BindingGetResultSetContext < U > ctx) throws SQLException
// SQLite's type affinity needs special care...
if (ctx.family() == SQLDialect.SQLITE)
String timestamp = ctx.resultSet().getString(ctx.index());
return timestamp == null ? null : new Timestamp(parse(Timestamp.class, timestamp));
else
return ctx.resultSet().getTimestamp(ctx.index());
【问题讨论】:
【参考方案1】:虽然您可以使用代码生成器注册自定义绑定,但请注意,此问题将在即将发布的 jOOQ 3.12 版本以及下一个 3.11 服务版本中得到解决。详情请见https://github.com/jOOQ/jOOQ/issues/8736。
【讨论】:
知道为什么 SQLite 在时间戳绑定中有一个特殊的检查和转换,而不是仅仅将时间戳传递给 JDBC 语句/结果吗? @MikeRuffing:SQLite 支持的第一次实现已经有一段时间了,但我认为这是因为 SQLite 的类型亲和性以及读取字符串格式日期时的相关问题。我认为 xerial JDBC 驱动程序根本无法处理所有可能的日期格式,因此为了解决任何可能的限制,我们推出了自己的。以上是关于在 SQLite 中使用 DATETIME 列时如何避免 NumberFormatException?的主要内容,如果未能解决你的问题,请参考以下文章
SQLITE 在alter表添加列时怎么判断表中是不是已经存在列