Object-Relational Mapping
This article looks at how GORM works. It compares and contrasts GORM with Hibernate, focusing on three areas: defining object-relational mapping; performing basic save, load, and delete operations on persistent objects; and executing queries. It describes how GORM leverages the dynamic features of Groovy to provide a different flavor of ORM that has some limitations but for many applications is much easier to use.
GORM is the persistence component of Grails, which is an open source framework that aims to simplify Web development. Grails is written in Groovy, a dynamic, object-oriented language that runs on the JVM (Java Virtual Machine). Because Groovy interoperates seamlessly with Java, Grails can leverage several mature Java frameworks. In particular, GORM uses Hibernate, a popular and robust ORM framework.
GORM, however, is much more than a simple wrapper around the Hibernate framework. Instead, it provides a very different kind of API. GORM is different in two ways. First, the dynamic features of the Groovy language enable GORM to do things that are impossible in a static language. Second, the pervasive use of CoC ( Convention over Configuration) in Grails reduces the amount of configuration required to use GORM. Let’s look at each of these reasons in more detail.
to add methods and properties to a class at runtime. The simplest approach is to define propertyMissing() or methodMissing() methods. The propertyMissing() method is called by the Groovy runtime when the application attempts to access an undefined property. Similarly, the methodMissing() method is called when the application calls an undefined method. These methods enable an object to behave as if the property or method existed.
The second and more sophisticated approach is to use the wonderfully named ExpandoMetaClass. Every Groovy class has a metaClass property that returns an ExpandoMetaClass. An application can add methods or properties to a class by manipulating this metaclass. For example, figure 1 is a code snippet that adds a method to the String class that concatenates a string with itself.
This code snippet obtains the String metaclass and assigns to its doubleString property a closure (a kind of anonymous method) that implements the new method.
Groovy applications often use methodMissing() and ExpandoMetaClass together. The first time an undefined method is invoked, missingMethod() defines the method using the ExpandoMetaClass. The next time around, the newly defined method is called directly, thereby bypassing the relatively expensive missingMethod() mechanism.
Later you will see how Grails uses methodMissing() and ExpandoMetaClass to inject persistence-related methods and properties into domain classes at runtime, thereby simplifying application code.
DYNAMIC GROOVY
GORM relies heavily on the dynamic capabilities of the Groovy language. In particular, it makes extensive use of Groovy’s ability to define methods and properties at runtime. In a static language such as Java, a property access or a method invocation is resolved at compile time.
In comparison, Groovy does not resolve property accesses and method invocations until runtime.
A Groovy application can dynamically define methods and properties.
Groovy provides a
couple of different ways
CONVENTION OVER CONFIGURATION
The second key idea in GORM is CoC. Its premise is that a framework should have sensible defaults and should not require developers explicitly to configure every facet; instead, only the exceptional cases should require configuration. CoC was first popularized by the Rails and Grails frameworks, but mainstream Java EE frameworks including Spring9 have begun to adopt the concept. Today, developers expect modern Java EE frameworks to require much less configuration than older frameworks.
CoC is used throughout Grails. For example, built-in defaults determine how to map an HTTP request to
g r oovy:000> String.metaClass.doubleString={->delegate+delegate} = ==> groovy.lang.ExpandoMetaClass$ExpandoMetaProperty@14a18d g roovy:000> “ACM Queue”.doubleString() = ==>ACMQueueACMQueue
References:
Archives