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

References:

Archives