Bind a value to a named parameter in a Hibernate query
Tested on |
Hibernate (3.6.9) |
Objective
To bind a value to a named parameter in a Hibernate query
Background
In HQL (as with SQL) it is considered bad practice to pass arguments into a query by directly inserting the required values as strings. The most important reason for this is to protect against injection attacks (which are possible in HQL, despite the lack of support for comments as such). The solution for both SQL and HQL is the same: use a placeholder within the query string to represent the parameter, then bind the placeholder to the required argument value using a mechanism provided by the query API.
Other benefits of this approach are that it is more robust to non-malicious errors, potentially more efficient, and able to refer to objects which cannot easily be represented as strings.
Scenario
Suppose that you are attempting to refactor a program containing the following function:
public final Page getPageByUrl(String url) throws NoResultException { return em.createQuery("FROM Page WHERE url = '" + url + "'", Page.class) .getSingleResult(); }
You wish to obtain equivalent functionality without interpolating the URL argument into the query string. The identifier em
refers to the relevant EntityManager
instance. The class Page
is capable of being persisted, and has a property named url
of type String
.
Method
The desired effect can be achieved by:
- replacing the URL literal with a named parameter introduced by a colon, then
- binding an argument to the parameter using the
setParameter
function.
In this instance url
would be a reasonable name for the parameter:
public final Page getPageByUrl(String url) throws NoResultException { return em.createQuery("FROM Page WHERE url = :url", Page.class) .setParameter("url", url) .getSingleResult(); }
Note that the name url
being used for three different but related purposes within this function:
- As the single parameter to the function
getPageByUrl
, and as the second argument tosetParameter
, it is a JavaString
object. - As its first occurrence in the query string it is an HQL property name.
- As its second occurrence in the query string, and as the first argument to
setParameter
, it is a named parameter. The former is prefixed by a colon to indicate that it is a parameter, whereas the latter is not.
Alternatives
HQL also supports positional parameters, using the same representation as JDBC (a question mark for each instance). The function used to bind values has the same name (setParameter
), but takes an integer as the first argument as opposed to a string. Parameters are numbered from one:
public final Page getPageByUrl(String url) throws NoResultException { return em.createQuery("FROM Page WHERE url = ?", Page.class) .setParameter(1, url) .getSingleResult(); }
Further Reading
Tags: java