如何在Jooq处理日期?

时间:2013-11-11 06:17:42

标签: java sql jooq

当我们使用普通JDBC连接时,我们使用下面的代码来格式化日期或转换日期

 if(argDB.equals("Oracle")){
       sb.append(" AND TO_CHAR(PaymentDate, 'YYYY-MM-DD') <= TO_CHAR(SYSDATE,'YYYY-MM-DD')");
          }
 else {
       sb.append(" AND CONVERT(VARCHAR(8), PaymentDate, 112) <= CONVERT(varchar(8), dbo.getdate(), 112)");
           }

现在我们正在使用JOOQ您认为我们必须像以前一样转换日期,或者JOOQ可以在内部处理此类问题吗?正如我现在检查JOOQ不支持TO_CHAR方法的Oracle和Lukas给出了一些替代方法Here

1 个答案:

答案 0 :(得分:5)

编写谓词的更好方法

由于您只是将日期格式化以比较它们,因此您应该只比较日期值本身,这将更快,因为您的数据库将能够使用索引:

-- In SQL
ACCOUNT_PAYMENT.PAYMENT_DATE <= SYSDATE
// In jOOQ
ACCOUNT_PAYMENT.PAYMENT_DATE.le(DSL.currentDate())

实施与方言无关的自定义TO_CHAR()功能。

您应该为此目的创建CustomField。这将允许您与jOOQ的查询呈现和变量绑定生命周期进行交互,以便根据RenderContext的基础SQLDialect呈现SQL方言特定子句。从本质上讲,这归结为写作(假设jOOQ 3.2 API):

class ToChar extends CustomField<String> {
    final Field<?> arg0;
    final Field<?> arg1;
    ToChar(Field<?> arg0, Field<?> arg1) {
        super("to_char", SQLDataType.VARCHAR);
        this.arg0 = arg0;
        this.arg1 = arg1;
    }
    @Override
    public void toSQL(RenderContext context) {
        context.visit(delegate(context.configuration()));
    }
    @Override
    public void bind(BindContext context) {
        context.visit(delegate(context.configuration()));
    }
    private QueryPart delegate(Configuration configuration) {
        switch (configuration.dialect().family()) {
            case ORACLE:
                return DSL.field("TO_CHAR({0}, {1})", 
                    String.class, arg0, arg1);

            case SQLSERVER:
                return DSL.field("CONVERT(VARCHAR(8), {0}, {1})", 
                    String.class, arg0, arg1);

            default:
                throw new UnsupportedOperationException("Dialect not supported");
        }
    }
}

然后,您可以编写自己的静态实用程序方法:

public class MyDSL {
    public static Field<String> toChar(Field<?> field, String format) {
        return new ToChar(field, DSL.inline(format));
    }
}