This example creates a Customer object and saves it in
the database by 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
missingMethod()/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 (See “BASE: An ACID Alternative,” by Dan
Pritchett, in this issue of Queue).
TRADITIONAL ORM QUERIES
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 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 meth-
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.
c la ssAccountDaoImpl..{
p ublic List<Account> findByBalanceLessThan(double threshold) {
Session session = Session.currentSession();
Query query = session.createQuery(“from Account where balance < ?”)
query.setParameter( 1, threshold);
return (List<Account>) query.list();
}
A
class AccountDaoImpl .. {
public List<Account> findByBalanceLess Than(double threshold) {
Criteria c = session.createCriteria( Account.class)
c.add( Restrictions.lt(“balance”, threshold))
return c.list();
}
B
FIG 4