Site icon Java, SQL and jOOQ.

When to Use jOOQ and When to Use Native SQL

A frequently encountered doubt people have when using jOOQ is to decide when a “complex” query should be written using jOOQ API vs. when it should be implemented using native SQL.

The jOOQ manual is full of side by side examples of the same query, e.g.

Using jOOQ:

ctx.select(AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME, count())
   .from(AUTHOR)
   .join(BOOK).on(AUTHOR.ID.eq(BOOK.AUTHOR_ID))
   .groupBy(AUTHOR.ID, AUTHOR.FIRST_NAME, AUTHOR.LAST_NAME)
   .fetch();

Using native SQL:

SELECT author.first_name, author.last_name, COUNT(*)
FROM author
JOIN book ON author.id = book.author_id
GROUP BY author.id, author.first_name, author.last_name;

In the native SQL case, do note that you can still use jOOQ’s plain SQL templating API, ideally using Java text blocks, so you can still profit from a few jOOQ things, including:

With jOOQ, you’d then write:

ctx.fetch(
    """
    SELECT author.first_name, author.last_name, COUNT(*)
    FROM author
    JOIN book ON author.id = book.author_id
    GROUP BY author.id, author.first_name, author.last_name
    """
);

The obvious pros and cons

First off, there are some obvious pros and cons of using jOOQ in any given setting.

Pros:

You’ll hardly find anything better than jOOQ:

All the pros are explained in the articles linked from the above links, so I won’t repeat the benefits here anymore.

Cons:

jOOQ can get in the way occasionally:

Let’s quickly look at these two items.

The best of both worlds

jOOQ won’t try to make you use jOOQ where it doesn’t fit. In a previous article, we’ve already elaborated when an ORM (implementing object graph persistence) works better. In this case, we’re discussing pure SQL, where jOOQ shines compared to ORMs, but it may not be right for certain “kinds of SQL queries.”

Those kinds are complex static queries. From a jOOQ perspective, you can get very very far, unless you’re using some really advanced vendor specific SQL feature, like the Oracle MODEL clause. But these things are a matter of taste. What jOOQ recommends you do in case you feel a certain query is too complex for jOOQ is to either:

Or maybe even better, extract its logic into:

Views are supported by all major RDBMS and very underappreciated. Table valued functions can be even more composable, as they take arguments, and can even be inlined by some RDBMS (e.g. SQL Server). In both cases, you get to keep your native SQL syntax, but at the same time, you profit from type safety as the objects are compiled by the RDBMS.

Plus, as I’ve mentioned before, we really recommend you follow a TDD approach to developing your application, using integration tests. If you do that, then adding views and table valued functions to your schema using Flyway or Liquibase or any other means of database change management will be straightforward.

After the change is applied, you’ll regenerate your jOOQ code, and you can immediately use the new schema object in your Java application without any loss of type safety.

Using such a pragmatic approach, you can get the best of both the jOOQ and the native SQL worlds.

Exit mobile version