Named Queries strike back
QUERY word concept image via Shutterstock
Although they are known to have an advantage over most other APIs for persistence access, JPA Named Queries have a rather shadowy existence. Developers don’t like them because they cause too much coding headaches. But boilerplate code is not an excuse any longer!
Named queries for database access from Java code have been around for a while now. They are a kind of SQL statements wrapped into annotations and attached to entity classes. In this way they are registered in the EntityManager which will provide the query instance later on, ready to be configured and finally to be executed. Figure 1 shows a simplified User entity class holding a parameterized query to find all users with the given name.
Figure 2 presents the glue code to execute that query.
This method is highly specific. Its signature reflects the expected query behavior, e.g. the result type and the parameter fits to the query.
In contrast, the method body makes use of the highly generic APIs of EntityManager and Query. To be able to cope with every possible query statement, those APIs are mainly untyped and string-based. As a result, string values from the query annotation have to be repeated here („User.findByName“, „theName“).
This kind of glue code is needed again and again for every query. It is just a cumbersome task which may explain why alternatives such as the Criteria API, QueryDSL, or Spring Data JPA have been invented. But most of those approaches lead to dynamically constructed statements, which are created over and over again for every execution.
Hence an often cited golden rule (e.g. Pro JPA 2) suggests that users avoid dynamic queries to gain better performance wherever possible. This measure leads back to static named queries and the corresponding glue code. But with a small tool you can simplify the implementation and earn the performance advantage as well.
The Anqu Method Pattern
The Anqu Method Pattern aims to minimize the disadvantages of JPA named queries while preserving their advantages. It is a coding or design recommendation for @NamedQueries and as such it is independent of any IDE. The Anqu Method Pattern consists of three proposals:
Glue code in a single method: The glue code for a given named query should only exist once. It should be wrapped by a typed method and the query execution should be this method’s only purpose.
Deep glue code: The method containing the glue code should be placed in an application layer as deep as possible. The location of the method should be standardized by some design rule.
Test the contract: The implementation of a named query requires code in different places, which are connected by the repetition of strings or reflective mechanisms. Those contracts should be verified automatically.
The Anqu Method Plug-in
The Anqu Method Plug-in for Eclipse supports all three steps mentioned above and makes the implementation workflow more comfortable. Anqu Method is generally used via its context menu. If an action deals with a concrete named query, the cursor has to be placed within the annotation of that exact query.
The typical workflow to implement the query from the User entity example could look like this:
Step 1: Generate a new @NamedQuery annotation skeleton by clicking Anqu Method → New Named Query. The query’s name will be initialized with the entity’s name.
Step 2: Complete the query’s name to „User.findByName“.
Step 3: In simple cases like „findByName“, the query statement can be derived from the name. Executing Anqu Method → Derive Statement will insert the statement into the annotation. It is also possible to derive statements from more complex query names. Otherwise this step means adding the statement manually.
Step 4: Glue code generation. This includes two decisions:
What kind of query execution is needed? For writing access (update, delete) or reading access (select) with possibly multiple results choose Anqu Method → Execution. If a ‘select’ is expected to return at most one result, Anqu Method → Single Result Execution should be used.
Where should the glue code go? Depending on the interpretation of the Anqu Method Pattern, the code could be placed in a DAO layer or as deep as possible in the entity class directly. To generate code into the entity class use → Method to Source. For other targets take a detour to the clipboard by selecting → Method to Clipboard, then paste the code into the desired target class.
Step 5: By clicking Anqu Method → … → Tests as Configured, JUnit tests to verify the contract can be created as well. Depending on the preferences, the target of this test code generation is a test class in the workspace or again the clipboard.
The plug-in’s configuration page is reachable via the menu item Anqu Method → Open Preferences. It is recommended to define the desired flavor of the Anqu Method Pattern in ‘preferences’ once. That could be called step 0. Developers mainly working in the persistence layer may wish to create some keyboard shortcuts for higher productivity. To do so, open the general preferences at Preferences → General → Keys and filter the list by the term ‘anqu’ to find all relevant commands.
In this simple example only the query’s name „findByName“ has had to be typed manually. Everything else has been obvious and thus has been generated.
Glue code in the entity?
The plug-in has emerged from a rather verbose pattern for the implementation of named queries. It had included several public string constants for the query name and all the query’s parameters. Those constants had been created to eliminate typos by enabling auto-completion in the IDE. To make sure the constants had been used consistently in the query statement and the glue code, the statement had manually been transformed into an unreadable concatenation of text fragments and constant appearances. Finally, this strategy had led to a reuse of constants, introducing an unnecessary coupling between independent queries.
As string constants (public static final) are already resolved at compile time, a wrong feeling of safety in the case of a refactoring has been introduced, too. Finally, to call the query, the user had had to remember all the required parameters and provide the code to define their values.
As a radical answer to that overhead, a plug-in has been created that hides the glue code directly in the entity class. If no developer ever needs to use those constants, there is no necessity to publish or even create them. The method is static, typed, and automatically requires all parameters. Logical code in entity classes may be controversial. Yet the deepest possible glue code location provides simplicity as well as encapsulation and centralization of all the code for a named query. The method is highly reusable since the EntityManager is one of its parameters.
With the glue code generation into the entity class, it is possible to trigger the test code generation with the same menu call: Anqu Method → … → Method to Source + Tests as Configured.
Test the contract!
The generated tests offer a sort of write protection for the code that is associated with the query. This applies to parts of the entity class, the query annotation, and the glue code. So if a relevant field in the entity is renamed, a test fails. If the statement is changed, a test fails. If the glue code is manipulated, a test fails. The tests try to mimic a compiler. They are based on the Mockito mocking framework which has to be in the classpath if these tests are used.
One of the tests will check all the references contained in the query statement on classes and fields. So a typo in a field name, e.g. u.nam instead of u.name, will also lead to an error. This can already be helpful during the implementation of the query statement.
The test bundle mentioned does not execute the query itself. A positive test result does not guarantee that the query will work in the runtime environment (deployment, persistence unit).
Query Mocking made easy
Isolated JUnit testing of classes often leads to the necessity to mock the behavior of the EntityManager. But mocking the execution of a @NamedQuery is cumbersome. Anqu Method can generate a so-called MockUtility class for every query. This class provides static methods to define the mock behavior in a simple way.
Do you call that a boilerplate?
The term boilerplate is associated with boring programming tasks producing obvious code. If the programming part is replaced by code generation, you might still call it a boilerplate – but do you still call it a problem?
As shown in the example workflow, in many cases the only thing that one has to manually type is the query name. The rest can be generated by just a few calls of the plug-in functionality. Compare it to your current workflow.
The plug-in is available at www.anqu-method.de and is free of charge. It includes further features such as pagination support or support for Spring Data JPA. There are not many reasons left to rely on a framework, which leads to the unforced use of dynamic queries.
Links and literature