The Evolution of Glue Code
This (polemic) section describes the motivation behind the plug-in in an evolutionary way starting from a given query ending in a mess. The section is based on experience... All the problems come from the reflective nature of named queries. Spoiler alert: The story has a happy ending.
Here is the query:
@NamedQuery(name = "User.findByName", query = "SELECT u FROM User u WHERE u.name = :name")
@NamedQuery(name = User.FIND_BY_NAME, query = "SELECT u FROM User u WHERE u.name = :name") public class User { public static final String FIND_BY_NAME = "User.findByName"; }
@NamedQuery(name = User.FIND_BY_NAME, query = "SELECT u FROM User u WHERE u.name = :" + User.PARAM_NAME) public class User { public static final String FIND_BY_NAME = "User.findByName"; public static final String PARAM_NAME = "name"; }
Query query = entityManager.createNamedQuery(User.FIND_BY_NAME); query = query.setParameter(User.PARAM_NAME, "theName");
Same problem: Renaming the query or a parameter consistently in class User forces all callers to compile again. Otherwise during runtime they will use wrong String values. Accessing the constants through methods is a way to fix this:
@NamedQuery(name = User.FIND_BY_NAME, query = "SELECT u FROM User u WHERE u.name = :" + User.PARAM_NAME) public class User { static final String FIND_BY_NAME = "User.findByName"; static final String PARAM_NAME = "name"; public static String getParamName() { return PARAM_NAME; } public static String getQueryNameFindByName() { return FIND_BY_NAME; } }
Query query = entityManager.createNamedQuery(User.getQueryNameFindByName()); query = query.setParameter(User.getParamName(), "theName");
What a Mess
But there still are problems:- A lot of time has been wasted
- The example is not even documented
- The query becomes illegible - especially with more parameters
- All those constants and methods make the class illegible
- The caller needs to know which parameters to set
- The caller needs to know which parameter types can be used
- When someone changes the query, code has to be changed manually
- The code needs test coverage
Cleaning Up
All you really wanted was an compiler checked API:public static Query getQueryFindByName(EntityManager entityManager, String name)
The caller can now write the following:
Query query = User.getQueryFindByName(entityManager, "theName");