The starting point

In a JEE you normally use the Java-Persistence-API JPA to access the data. JPA provides named queries which are statically defined queries with an unmodifiable query string. Because the query string is unmodifiable a client must still be able to provide parameters that concretize a query. Those query parameters are placed in the query string in a special format, e.g. :username.

So if we define a named query in the simplest way it will look like this:

Once a named query is defined we can use it. The EntityManager provides access to it.

This looks like a quite good solution. Just the client code must know the query parameters that we defined in named query. But this also means that we couple every client code to the query string and one developer who changes the query string might not know all places of client code where the query string parameters are used.

So, is there

  • better way?
  • a way that allows us to bring those things together that belong together?
  • a way to get compiler support?

In the following sections I will show you one approach of how to achieve these objectives.

Encapsulation of the named query

Before we start to improve something we should think about the problem from a client perspective.
The question always is “What would be a comfortable way for a client to use an API?”

If I look at the named queries in JPA from a client’s perspective, as a client I would like to write something like this:

From a client’s perspective this looks like a comfortable and safe API.
Now lets start to implement exactly this.

First of all the client wants to create an object that represents the query called OrdersByUsername. Thus we create this class.

Because the OrdersByUsername represents a specific query we also define the query’s name, the query string and it’s parameter names in this class.

After a client created an OrdersByUsername object and set the username he wants to call a DAO to find the orders.

Thus we implement that feature in an AbstractDao. Thus we want to make this feature available for all DAOs we also have to find an abstraction for the OrdersByUsername class. Let’s name this abstraction NamedEntityQuery. Furthermore the AbstractDao must have access to the query’s name, the parameters and the query string. We also place this access in the NamedEntityQuery.

Now we have to implement the abstraction of a named query that we use in the AbstractDao.

And now we let OrdersByUsername inherit the NamedEntityQuery.

Finally we adapt the JPA named query definition.

That’s it.

Closing Words

Someone might argue that the approach of decouple a query string and parameters from a client is a lot of stuff to do for just a simple query,
but someone should also keep in mind that this approach:

  1. Decouples the client from the query string.
    Thus the query string can be changed in order to refactoring the database without affecting the client.
  2. The query string parameter binding is type-safe and checked by the compiler.
    Even more sophisticated checks can be implemented like a not null check or a pattern match of the parameter to set.
    In the old approach this is also possible, but the validation logic will be scattered through the client code and might differ on any place.

I hope that this was an interessting blog about how things can else be done and that it inspired you so that you might develop a even better approach on your own.

If an API is not what we want it to be – we should change it.