数值超出范围减去jOOQ中的日期

时间:2015-03-16 08:45:51

标签: java h2 jooq

我正在尝试使用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]

2 个答案:

答案 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))
    ...

只是为了看看它是如何影响错误的。