calling save(). It then loads the customer by calling
Customer.get().
Finally, it deletes the customer by
calling delete(). Note that none of
these methods is defined in the source
code for the Customer class. GORM
implements them using the miss-ingMethod()/ExpandoMetaClass
mechanism described earlier.
GORM’s dynamically defined persistence methods eliminate a lot of
DAO code while decoupling application code from the ORM framework.
GORM sidesteps the problem of how
noncomponents obtain references
to DAOs. Code anywhere in a GORM
application can perform data-access
operations. Of course, whether that
is always appropriate is another issue
since, as I discuss later, it can result in
database-access code being scattered
throughout the application.
One significant limitation of GORM
is that it does not support multiple databases. A Hibernate application explicitly uses a particular session and
can thereby select which database to
access. A GORM application uses the
persistence methods that are injected
into domain classes and cannot select which database to use. Moreover,
as of the time of writing, the mechanism used for configuring GORM does
not support multiple databases. This
limitation might prevent many applications from using GORM, including
those that horizontally scale by using
multiple databases.
executing Queries
An application may not know the primary keys of the objects it needs to
load. Instead, it must execute a query
that retrieves objects based on the
values of their attributes. When using
a traditional ORM framework, an application executes queries by invoking
methods on API objects provided by
the framework. This code is usually
encapsulated by DAOs to decouple the
application from the ORM framework.
As with persistence methods, GORM
takes a different approach that often
simplifies application code.
Hibernate provides several ways to
execute queries. An application can,
for example, use the Query interface
to execute queries written in HQL (
Hibernate Query Language), which is a
powerful object-oriented, textual query
GoRm injects
persistence-related
methods into
domain classes
at runtime.
it eliminates a
significant amount
of data-access
methods and
classes, while
still decoupling
the business
logic from the
oRm framework.
language. Figure 4a is a DAO finder
that retrieves accounts with balances
less than some minimum.
This method obtains a Session
and creates a Query object. It then sets
the query’s parameter and executes the
query, which returns a list of Account
objects.
A Hibernate application can also
use the Criteria Query API to execute
queries. This API provides methods for
building a query programmatically. It
is especially useful when an application needs to build a query dynamically
since it eliminates the need to concatenate query string fragments. (Figure
4b is an example of a criteria query that
finds accounts with low balances.) This
code snippet creates a Criteria object for the Account class. It then adds
a restriction and executes the query.
One problem with the DAO finders
is that most have the same structure
as the example: create a query, set the
parameters, and execute the query. The
only variables are the query and the
parameters. As with the persistence
methods, these cookie-cutter methods
and the DAOs that contain them are tedious to develop, test, and maintain.
Dynamic GoRm finders
GORM has a dynamic finder mechanism that eliminates the need to write
simple queries and DAO finder methods. 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 meth-
54 communicAtionS of the Acm | APriL 2009 | voL. 52 | no. 4