我正在尝试使用H2数据库(v1.4.185)比较jOOQ(v3.5.0)中的日期,但如果比较太大,我会得到“数值超出范围”。
例如,使用下表
CREATE TABLE example (
id INT AUTO_INCREMENT,
deadline TIMESTAMP,
PRIMARY KEY (id)
);
并使用以下示例代码(jOOQ的代码生成步骤未显示)
DSLContext dsl = DSL.using(getDataSource(dbUrl), SQLDialect.H2);
ExampleRecord exampleRecord = dsl.newRecord(EXAMPLE);
exampleRecord.setDeadline(Timestamp.valueOf("2001-01-10 12:15:30"));
exampleRecord.store();
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(
DayToSecond.valueOf(Duration.ofDays(30).toMillis()))
.le(currentTimestamp()))
.fetch().forEach(record -> System.out.println(record.getDeadline()));
产生以下错误
Exception in thread "main" org.jooq.exception.DataAccessException:
SQL [select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp()];
Numeric value out of range: "-2592000000";
SQL statement:
select "EXAMPLE"."ID", "EXAMPLE"."DEADLINE" from "EXAMPLE"
where dateadd('ms', cast(? as bigint), "EXAMPLE"."DEADLINE")
<= current_timestamp() [22003-185]
答案 0 :(得分:3)
看起来H2中的一个缺陷给了我。 H2&#39; DATEADD()
function expects the number of units added to be of type int
。当然,在毫秒运行时,这没有任何意义。 I've reported it on the H2 user group。让我们看看他们说了什么。如果在H2中无法解决这个问题,我们将在jOOQ中解决这个问题,因为我们已经使用Sybase和其他数据库。
用于日期时间算法的Field.sub(Number)
方法已经从时间戳(如Oracle)中减去了几天。所以,可以编写相同的表达式:
EXAMPLE.DEADLINE.sub(30)
另一种选择是改为使用DSL.timestampAdd()
:
timestampAdd(EXAMPLE.DEADLINE, -30, DatePart.DAY);
第三种选择是使用纯SQL:
public static Field<Timestamp> mySub(Field<Timestamp> field, Number days) {
return DSL.field("dateadd('day', {0}, {1})", Timestamp.class, val(-days), field);
}
答案 1 :(得分:2)
这个错误对我没有意义。生成的SQL(bigint
)表明jOOQ知道参数是long
且-2592000000
完全在限制范围内。
我想知道引号是由错误消息添加的,还是DayToSecond.toMillis()
可能会返回String
而不是long
。除了我预期会有不同的错误消息(加上编译错误)。
为了安全起见,尝试通过用常量替换代码来降低表达式的复杂性:
dsl.selectFrom(EXAMPLE)
.where(EXAMPLE.DEADLINE.sub(-2592000000L))
...
只是为了看看它是如何影响错误的。