The Anqu Method Pattern

The anqu method pattern for Java suggests to have a central method to access a @NamedQuery or @NamedNativeQuery. In short the pattern proposes the following construction for a given query:
Example

You may already be using this pattern in some variation - you could call it common sense. What is not shown is the method body containig the glue code to execute the query. It is cumbersome to implement and the API to use is one of the most general APIs you can think of. Nearly every parameter is either just Object or at best String. Writing that code is error-prone.

Building the bridge between the textual nature of the @NamedQuery statement and the modeled Java world early reduces risks and enables you to use compiler based tooling to increase coding comfort.

Driven by this the anqu method pattern consists of three principles:

Single Point of Transition:
Have a single method in your code to do the transition to the modeled Java world for a query. Do not repeat the glue code somewhere else and do not let this method do anything else.
Early Transition:
Do the transition from the query statement to the Java world as early/deep in your layers as possible.
Test the Contract:
Have tests to ensure that the three parts dealing with the query (the Java model, the query statement, and the glue code) always fit together.

If you use Eclipse as IDE, the anqu method plug-in can generate the Java method in a few mouse clicks. You get a specialized, typed, already implemented, and unit-tested API for every query. The plug-in helps to implement all steps mentioned above and has addtional features to increase productivity.

Please note that in the example above the EntityManager is provided as a parameter of a static method. Though this is optional/configurable, this variation is considered to be the earliest transition you can come up with.

Plug-In Capabilities

The following picture shows how the main functionalities of anqu method improve the typical workflow of creating and using a named (maybe native) query:

Plug-In Capabilities

anqu method generates access methods to named queries. The derived methods will encapsulate query creation and parameter preparation. The parameters of the query will be the parameters of the method - and they will be typed. In the most basic version the method will return the created query. You have to execute it yourself.

If you let anqu method try better, you can let it generate a method that not only creates and configures the query but also executes it. In case of a Select you will get a List as a result. anqu method will try to derive the type of objects in the List and provide a typed List. Deriving the return type is not always possible. You may end up with Object as best guess. In case of an update or delete you will get the number of affected rows as a result.

If you know that the query will at most return one result object, you can let anqu method generate a single/first result method. It will return null if there was no result.

Another possibility is to generate methods with pagination support. There will be additional parameters for starting point and page size.

anqu method can also generate JUnit 4 tests for the productive methods providing full code coverage and regression safety to some extend.

In addition to that the plug-in supports you in adding a @NamedQuery to an existing class. It will generate such an annotation and if there already is one, it will wrap around the necessary @NamedQueries annotation automatically.

Even writing the query statement can be omitted if the query name follows some simple rules. In this case just derived the statement from the query name. Most simple examples are "findByName" and "Xyz.deleteAll".

It is also possible to generate the glue code to access a @NamedQuery from a Spring Data or Apache DeltaSpike Data repository.

Mocking the EntityManager (and Query) in unit tests to avoid building a container environment is a common strategy. But programming the mocks is cumbersome. Anqu can create Mock Utility classes with static helper methods to program the EntityManager mock easily. Generate a Mock Utility specific for a query or create a generic Mock Utility for all queries, hence with a less comfortable API. If the query statement is simple enough to be derived from the query name, that query name is the only thing which has to be written by the programmer. All the other code can be generated.

Usage

Auto Completion

The most important features are now available via Eclipse auto completion. Functionality depends on the context:

Cursor Location Functionality
Outside a @NamedQuery annotation
Add @NamedQuery annotation to code.
Inside @NameQuery annotation, directly after dot/period in the name attibute
Get proposals for query names, e.g. findAll and find-methods for every field. Selecting a proposal also derives the statement and fills the query attribute.
Inside @NameQuery annotation, at first position of the query attribute
Derive the statement from the name attribute.
Anywhere else inside the @NameQuery annotation
Get proposals for query execution methods.

Adding a Named Query

To add a named query to an existing class open the context menu from the Java source code editor and select Anqu Method, then select New Named Query or New Named Native Query as shown below:

Add a NamedQuery with the context menu

A new and mostly empty @NamedQuery or @NamedNativeQuery annotation will appear in the source code ready to be edited.

Deriving Statements

In simple cases the name of the query is enough information to automatically derive the desired statement from it. Note that this only works for JP QL queries - not for native queries. Here is a short (reduced) description the grammar behind the recognition algorithm.

Semantics Keywords Comment
Select all objects
getAll, findAll, readAll, selectAll
No additions allowed
Delete all objects
deleteAll, delAll, removeAll
No additions allowed
Select objects
get, find, read, select
Combinable with restrictions and sorting
Delete objects
delete, del, remove
Combinable with restrictions
Field names
Camel case field name of the current entity, first character upper case.
E.g. NameOfStreet if there is a field String nameOfStreet in the entity class. Also works with cascading references such as StreetName if there is a field street of a class having a field name.
Update objects
update, set
E.g. setNameToNull, where name is a field of the current entity; Use 'and' to set more than one field: setNameToNullAndStreetToNull; Combinable with restrictions
Parameters for e.g. restrictions
Given + camel case parameter name
To distinguish between field references and intended parameters, parameters have to be prefixed bei Given
Restrictions
Where, By + field name; And, Or for chaining; Operators e.g. LessThan, EqualTo, IsNotNull and more!
Binary operators can cope with parameters and fields in both cases. Using By + field name indicates a query parameter for that field name.
Sorting
Order, Sort, Asc, Ascending, Desc, Descending, By
Various combinations such as OrderAscBy + field name or SortBy + field name + DescendingBy + other field name are possible. Sort and Order are not needed in cases like AscBy + field name

Generating Methods

To distinguish the created methods the terms productive methods and test methods are used in this section.

When creating methods, you need to set the cursor into the @NamedQuery or @NamedNativeQuery and open the context menu. Please note that just opening the context menu while the mouse pointer is over the query will not work. It really depends on where the cursor is in the editor.

Now choose Anqu Method and select the desired action in two steps:

Context menu

  1. What kind of method to generate
    • Method executing the query
    • Method executing the query, returning one (the first) result
    • Method creating the query and returning it
    • First/Max method executing the query - with firstResult and maxResults as parameters
    • First/Max method creating the query and returning it - with firstResult and maxResults as parameters
  2. Productive and/or test code and the target(s)
    • (Productive) Method to source file holding the query and tests as configured (see settings)
    • (Productive) Method to source file holding the query
    • (Productive) Method to clipboard
    • Tests as configured (see settings)
You can open the help page of this plug-in via the context menu as well as its preference page. See the next section on possible configurations.

Removing Code

You can remove a @NamedQuery, the corresponding glue code, the generated tests, and the generated MockUtility with this functionality. It is also possible to remove all the code but the @NamedQuery itself.

Remove menu

This will not remove code that has been generated into the clipboard and has been pasted somewhere. Only the following locations are cleaned up if present:

Settings

All settings described in this section are global. The ?-buttons give descriptions of the options.

Options for Generated Methods

Settings for the method

Options for Test Code

Test settings

Suppression of Warnings

Warning settings

Deriving Statements

Derive Statements settings

Removing Code

Removal options

JPA Version Specific Features

JPA version activation

Unit Tests

The generated test methods have the following goals: Several test methods are generated for a single productive method. Of course all of them take part in the coverage goal (which is the only goal that can be reached for sure). Some tests try to protect the code from becoming inconsistent due to manual changes. This is based on some heuristics. Especially checking that the method's code is unchanged is done in a rather optimistic way. If a test fails, first thing to do is to check the query semantically. If it is correct, re-generate the productive method and the test methods. If a newly generated test fails, this plug-in has a bug.

For clarification: The generated test methods do not test the query's semantics, not even if the query is syntactically correct.

Mock Utilities

Anqu method can simplify mocking query executions by creating Mock Utility helper classes. A query specific Mock Utility class contains static methods to program a given EntityManager mock to return the provided values or to throw the provided RuntimeException.

Also a generic Mock Utility can be generated being able to mock any @NamedQuery execution. The API of the generic Mock Utility is powerful, yet not as comfortable to use as a query specific one. The generic utility is considered a fallback.

Naming Recommendations

This plug-in generates methods from queries just like 'Generate getters and setters' generates methods from fields. In both cases names have to be found. As a query's name has big impact on the name of the generated method, please consider the following recommendations: This plug-in will split the full query name and try to find the suffix using the assumption that the above recommendations have been met. You will get well named methods. Example: The query names "MyEntity.findByName", "MyEntity findByName" "MyEntity:findByName" will all result in a method named "findByName". If you generate a method to return the query object itself (without executing the query) the method's name will be prefixed by the text 'getQuery' or whatever you defined in the preferences.

Known Limitations