使用 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();                

有几种方法可以解决这个问题:

使用ConverterBinding转换类型

您可以在源代码生成器中注册数据类型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

您当然可以在数据库中使用 BIGINTBIGINT UNSIGNED 而不是 TIMESTAMP。这样,您将始终自动拥有整数 unix 时间戳值。为了完整起见,这只是一种解决方法。