Object-Relational
Mapping
ORM
in Dynamic
Languages
ods. It uses Groovy’s dynamic capabilities to add finder
methods to domain classes. For example, an application
can find accounts with low balances, as shown in figure
5A. Provided that the method name follows certain naming conventions, the missingMethod()/ExpandoMetaClass
mechanism intercepts the call to the method and defines
a method that parses the method name to build a query
and executes it.
GORM dynamic finders support a rich query language.
Finder method names can use comparison operators
such as equals, less than, and greater than. They can also
use the and, or, and not logical operators. Even though
the query language is limited to the properties of a
single class—no joins—many queries can be expressed
as dynamic finders. A GORM application contains much
less data-access code and has far fewer explicit dependencies on the Hibernate framework. In addition, because
the finder methods are readily available on the domain
classes, GORM avoids the problem of needing to resolve
inter-component references.
One potential drawback of these finder methods is
that the method name is the definition of the query. It’s
not always possible to define an intentional revealing
name for a query that encapsulates the actual implementation. As a result, evolving business requirements can
cause the names of finder methods to change, which
increases the cost of maintaining the application.
method, which GORM injects into each domain class. It
takes an HQL query and a list of parameters as arguments.
One nice feature of this API is that it allows an application to execute an HQL query without explicitly invoking
the Hibernate API. The application does not have to solve
the problem of obtaining a reference to a DAO or other
component. One drawback, however, is that knowledge
of HQL is hardwired into the application.
The other option, which is especially useful when
constructing queries dynamically, is to use GORM criteria
queries, which wrap the Hibernate Criteria API described
earlier. As with the other APIs, GORM dynamically injects
a createCriteria() method into domain classes. This
method allows an application to construct and execute
a query without having an explicit dependency on the
Hibernate API.
Figure 5C is the GORM criteria query version of the
query that retrieves accounts with low balances. The
createCriteria() method returns an object for building
queries. The application executes the query by calling
list(), which takes a Groovy closure as an argument and
returns a list of matching objects. The closure argument
contains method calls such as lt() that add restrictions to
the query.
Applications can use these APIs to execute queries
that are not supported by dynamic finders. One potential
downside, which could be considered to be a weakness of
GORM, is the potential lack of modularity and violation
of the Separation of Concerns principle. There is a risk of
scattering the data-access operations for a domain class
throughout the application. Some data-access methods
are defined by the domain class, but the rest are intermingled with the application’s business logic, which could be
d e faccounts=Account.findAllByBalanceLessThan(threshold)
A
WHEN DYNAMIC FINDERS
ARE INSUFFICIENT
For applications that need
to execute more elaborate
queries, GORM provides a
couple of different options.
An application can execute
HQL queries directly. For
example, an application
can execute an HQL query
to retrieve accounts with
low balances, as shown in
figure 5B. This code snip-
pet invokes the findAll()
B
L ist accounts = Account.findAll(“from Account where balance < ?”,
[threshold])
C
def c = Account.createCriteria()
def results = c.list {
lt(“balance”, threshold)
}
FIG 5