使用 JOOQ 查询 Unix 时间戳
Querying Unix Timestamp using JOOQ
我正在使用 MySQL 服务器,我正在尝试使用 JOOQ API 检索时间戳。但是,我认为默认的 JOOQ 行为 returns 是本地时区的时间,而不是 UTC(它没有使用 UNIX_TIMESTAMP()
。使用 JOOQ,我的查询看起来像
db.select(USER_TABLE.REGISTERED_ON)
.from(USER_TABLE)
.where(USER_TABLE.EMAIL.equal(email)
.fetchAny()
然而,我要执行的sql应该是这样的
SELECT UNIX_TIMESTAMP(schema.table.timestamp_col)
FROM schema.table
WHERE email="someone@domain.com"
是否可以使用 JOOQ API?如果没有,运行 这个查询的最佳方法是什么,因为我真的希望能够使用生成的代码(USER_TABLE、USER_TABLE.REGISTERED_ON 等)。
编辑: 我现在正在执行以下操作,但它安全吗?基本上我是从 JOOQ 生成的 类.
中删除引文
String timestamp_field = USER_TABLE.REGISTERED_ON.toString().replace("\"", "");
Field<?> f = DSL.field("UNIX_TIMESTAMP(" + timestamp_field + ")");
Record r = db.select(f)
.from(USER_TABLE)
.where(USER_TABLE.EMAIL.equal(email))
.fetchAny();
有几种方法可以解决这个问题:
使用Converter
或Binding
转换类型
您可以在源代码生成器中注册数据类型Converter
or Binding
。这样,代码生成器将为数据库中的每个 TIMESTAMP
字段生成一个 Field<YourType>
。可能有用的类型是:
java.lang.Long
java.time.Instant
java.time.OffsetDateTime
(注意 jOOQ 3.7 将通过 [#4338] 支持)3
使用普通 SQL
每次要使用 UNIX_TIMESTAMP()
函数进行显式转换时,请使用 plain SQL。您的解决方案有效:
String timestamp_field = USER_TABLE.REGISTERED_ON.toString().replace("\"", "");
Field<?> f = DSL.field("UNIX_TIMESTAMP(" + timestamp_field + ")");
但不推荐,因为:
- 你应该永远不要依赖任何Java类型的任何
toString()
实现。
- 你通常应该尽量避免使用 jOOQ 的普通字符串连接 SQL API
更好的解决方案是:
DSL.field("UNIX_TIMESTAMP({0})", Long.class, USER_TABLE.REGISTERED_ON);
甚至:
public static Field<Long> unixTimestamp(Field<Timestamp> arg) {
return DSL.field("UNIX_TIMESTAMP({0})", Long.class, arg);
}
在数据库中使用BIGINT
您当然可以在数据库中使用 BIGINT
或 BIGINT UNSIGNED
而不是 TIMESTAMP
。这样,您将始终自动拥有整数 unix 时间戳值。为了完整起见,这只是一种解决方法。
我正在使用 MySQL 服务器,我正在尝试使用 JOOQ API 检索时间戳。但是,我认为默认的 JOOQ 行为 returns 是本地时区的时间,而不是 UTC(它没有使用 UNIX_TIMESTAMP()
。使用 JOOQ,我的查询看起来像
db.select(USER_TABLE.REGISTERED_ON)
.from(USER_TABLE)
.where(USER_TABLE.EMAIL.equal(email)
.fetchAny()
然而,我要执行的sql应该是这样的
SELECT UNIX_TIMESTAMP(schema.table.timestamp_col)
FROM schema.table
WHERE email="someone@domain.com"
是否可以使用 JOOQ API?如果没有,运行 这个查询的最佳方法是什么,因为我真的希望能够使用生成的代码(USER_TABLE、USER_TABLE.REGISTERED_ON 等)。
编辑: 我现在正在执行以下操作,但它安全吗?基本上我是从 JOOQ 生成的 类.
中删除引文String timestamp_field = USER_TABLE.REGISTERED_ON.toString().replace("\"", "");
Field<?> f = DSL.field("UNIX_TIMESTAMP(" + timestamp_field + ")");
Record r = db.select(f)
.from(USER_TABLE)
.where(USER_TABLE.EMAIL.equal(email))
.fetchAny();
有几种方法可以解决这个问题:
使用Converter
或Binding
转换类型
您可以在源代码生成器中注册数据类型Converter
or Binding
。这样,代码生成器将为数据库中的每个 TIMESTAMP
字段生成一个 Field<YourType>
。可能有用的类型是:
java.lang.Long
java.time.Instant
java.time.OffsetDateTime
(注意 jOOQ 3.7 将通过 [#4338] 支持)3
使用普通 SQL
每次要使用 UNIX_TIMESTAMP()
函数进行显式转换时,请使用 plain SQL。您的解决方案有效:
String timestamp_field = USER_TABLE.REGISTERED_ON.toString().replace("\"", "");
Field<?> f = DSL.field("UNIX_TIMESTAMP(" + timestamp_field + ")");
但不推荐,因为:
- 你应该永远不要依赖任何Java类型的任何
toString()
实现。 - 你通常应该尽量避免使用 jOOQ 的普通字符串连接 SQL API
更好的解决方案是:
DSL.field("UNIX_TIMESTAMP({0})", Long.class, USER_TABLE.REGISTERED_ON);
甚至:
public static Field<Long> unixTimestamp(Field<Timestamp> arg) {
return DSL.field("UNIX_TIMESTAMP({0})", Long.class, arg);
}
在数据库中使用BIGINT
您当然可以在数据库中使用 BIGINT
或 BIGINT UNSIGNED
而不是 TIMESTAMP
。这样,您将始终自动拥有整数 unix 时间戳值。为了完整起见,这只是一种解决方法。