@Entity(name = "Action")The code looks like this, because when doing named queries in JPA the name need to be unique for the WHOLE persistence unit. So, we agreed about the naming convention "[entity name].[finder name]" for the name of the query.
@NamedQueries({
@NamedQuery(name = "Action.findAll", query = "SELECT o FROM Action o"),
@NamedQuery(name = "Action.findByExtCode", query = "SELECT o FROM Action o WHERE o.externalCode = ?1"),
@NamedQuery(name = "Action.findByDescription", query = "SELECT o FROM Action o WHERE o.description = ?1"),
@NamedQuery(name = "Action.findManualActions", query = "SELECT o FROM Action o WHERE o.manual=?1"),
@NamedQuery(name = "Action.findSelectedActions", query = "SELECT o FROM Action o WHERE o.actionType.id <> 3"),
@NamedQuery(name = "Action.findFlowActions", query = "SELECT o FROM Action o WHERE o.actionType.id=3"),
@NamedQuery(name = "Action.findByActionFlowId", query = "SELECT o FROM Action o JOIN o.actionFlows af WHERE af.id = ?1")
})
It is actually quite nicer an more manageable than EJBQL in xml files, but still there is quite a bunch of copy/paste, String that are not constants, and the usage of named queries is here more problematic than EJB 2.0 home interfaces.
The usage looks like:
Query namedQuery = em.createNamedQuery("Action.findByExtCode");And this is for only one parameter...
namedQuery.setParameter(1, "001");
ActionBean actionBean = (ActionBean) namedQuery.getSingleResult();
The possible code errors (due to lack of static typing) we get here are:
- Errors on the string name for the namedQuery
- Errors on the parameter position (the named queries annotation is in the model not close to the business logic executing queries)
- Errors in Casting
It is quite clear looking at the code above, a JPA named query can be defined as an interface method. It has:
- a name (entityName + methodName),
- a list of parameters (ordered or named),
- and a result (list or single).
ActionQuery actionQuery = NamedQueriesFactory.getQueryProxy(ActionQuery.class, em);And the Queries interface:
ActionBean action = actionQuery.findByExtCode("001");
@JpaQueriesInterface(prefix = "Action")Which gets all the advantage of strong Java typing.
public interface ActionQuery {
public Collection<ActionBean> findAll();
public ActionBean findByExtCode(String extCode);
@JpaQueryUseParamNames
public ActionBean findByDescription(@JpaParamName("description")String description);
public Collection<ActionBean> findManualActions(boolean manual);
public Collection<ActionBean> findSelectedActions();
public Collection<ActionBean> findFlowActions();
public Collection<ActionBean> findByFlowActionId(long flowActionId);
}
So, the code of my small running example is here:
http://subversion.jfrog.org/jfrog/greenhouse/jpa/trunk/ and it's using maven of course...
Now, the next step is to use the Annotated Query Interface has NamedQuery provider so it will really look like JDBC 4.0.