JOOQ Facts: SQL functions made easy

(Last Updated On: January 4, 2018)

Introduction

The JDBC API has always been cumbersome and error-prone and I’ve never been too fond of using it. The first major improvement was brought by the Spring JDBC framework which simply revitalized the JDBC usage with its JdbcTemplate or the SqlFunction classes, to name a few. But Spring JDBC doesn’t address the shortcoming of using string function or input parameters names and this opened the door for type-safe SQL wrappers such as jOOQ.

JOOQ is the next major step towards a better JDBC API and ever since I started using it I knew there was no turning back. JOOQ became my number one choice for building dynamic queries and recently it became my standard SQL function wrapper.

SQL Function

To prove it, I will start with a simple SQL function:

CREATE FUNCTION FORMAT_TIMESTAMP (IN_TIME TIMESTAMP) RETURNS CHAR
    RETURN TO_CHAR(IN_TIME, 'DD-MON-YYYY HH24:MI:SS.FF');

While you should never ever use your database for formatting a Date, since that’s the job of your application logic, for the sake of testing let’s concentrate on the input and output variable types since that’s where JOOQ excels over any other JDBC APIs.

Using Spring SqlFunction

With Spring this is how I’d call it:

@Resource
private DataSource localTransactionDataSource;

@Override
public String formatTimestamp() {
    SqlFunction<String> sqlFunction =
        new SqlFunction<String>(localTransactionDataSource, "{ ? = call FORMAT_TIMESTAMP(?) }", new int[]{Types.TIMESTAMP});
    return (String) sqlFunction.runGeneric(new Date[]{new Date()});
}

This is way better than standard JDBC API but I don’t like to use String parameter names or casting the return value. Since HSQLDB doesn’t support using OUT parameters for SQL functions I cannot make use of StoredProcedure or SimpleJdbcCall which might have offered a better alternative to the SqlFunction example.

Using jOOQ

Let’s see how you can call it with jOOQ:

@Autowired
private DSLContext localTransactionJooqContext;

@Override
public String formatTimestamp() {
    FormatTimestamp sqlFunction = new FormatTimestamp();
    sqlFunction.setInTime(new Timestamp(System.currentTimeMillis()));
    sqlFunction.execute(localTransactionJooqContext.configuration());
    return sqlFunction.getReturnValue();
}

In my opinion, this is the most elegant SQL function wrapper I’ve ever used so far and that’s why it became my standard approach for calling SQL functions and procedures.

Code available on GitHub.

Subscribe to our Newsletter

* indicates required
10 000 readers have found this blog worth following!

If you subscribe to my newsletter, you'll get:
  • A free sample of my Video Course about running Integration tests at warp-speed using Docker and tmpfs
  • 3 chapters from my book, High-Performance Java Persistence, 
  • a 10% discount coupon for my book. 
Get the most out of your persistence layer!

Advertisements

4 thoughts on “JOOQ Facts: SQL functions made easy

  1. There are even more goodies! 🙂

    HSQLDB does support OUT parameters. I don’t know what this SourceForge issue is talking about. http://hsqldb.org/doc/guide/sqlroutines-chapt.html#src_formal_parameters
    While your usage of the “explicit” Routine API works well, you can also use the generated Routines helper class. This will allow you to write:

    
    String string = Routines.formatTimestamp(configuration, timestamp);
    

    You can also use such a function inline in your SQL statements:

    
    DSL.using(configuration)
       .select(formatTimestamp(TABLE.MY_TIMESTAMP))
       .from(TABLE)
       .fetch();
    
      1. I’ve been using a bulk-delete SQL function implemented on top of Spring StoredProcedure, and it worked for both Oracle and PostgreSQL, the two databases we’ve been supporting. I couldn’t make it work for the current HSQLDB (2.2.8), but maybe a new version will address this limitation.

Leave a Reply

Your email address will not be published. Required fields are marked *