a handler class. Similarly, GORM has rules for defining
which classes to persist and how to include defaults for
column and table names. Because of CoC, a typical Grails
application contains significantly less configuration code
and metadata than an application using a traditional
framework.
Now that we have looked at the key underpinnings of
GORM, let’s learn how to use it.
GORM MAPPING
A key part of using an ORM framework is specifying how
the object model maps to the database. The developer
must specify how classes map to tables, attributes map
to columns, and relationships map to either foreign keys
or join tables. This section looks at how this works using
a traditional ORM framework and then how it’s accomplished in Grails.
MAPPING WITH XML AND ANNOTATIONS
The persistent state of a Java class is either its fields or its
properties. A field is the Java equivalent of an instance
variable. A property is defined by getter and setter methods that follow the JavaBeans10 naming conventions. For
example, getFoo() and setFoo() define the property called
foo. The getter and setter methods often provide access to
a field of the same name as the property, although they
are not required to do so.
A Hibernate application
can map the fields or properties of domain classes to
the database schema using
either XML or annotations.
Figure 2 shows an annotation example on the left
and an XML example on
the right. Both examples
persist the fields of the Cus-
tomer class, but an applica-
tion can persist properties
either by annotating the private String name;
getter methods or by
omitting the default-access
attribute from the XML
document.
XML and annotations produce equivalent
metadata. They both
specify that the Customer
class is persistent. They
also specify that Hibernate
should generate an object’s primary key using whatever
mechanism is appropriate for the underlying database
and store it in the id field. The version field is configured
to store a Hibernate-maintained version number. They
both persist the name field and specify that the accounts
field represents a one-to-many relationship.
XML and annotations both have defaults for table
and column names. The table name defaults to the name
of the class and the column name defaults to the name
of the property. You can override these defaults using
extra annotations or XML attributes and elements. For
example, you can specify the table name using the @Table
annotation or the name attribute of the <class> element.
Each approach has benefits and drawbacks. One
advantage that XML has over annotations is that it
separates the O/R mapping from the Java code, which
decouples the domain classes from Hibernate. One problem with this separation is that it can be more difficult to
keep the mapping and code in sync. XML also tends to
be more verbose than annotations. Moreover, the XML
mapping must explicitly list all of the persistent properties of a class, whereas fields of certain basic types such as
Customer.name are automatically persistent when using
annotations.
Another problem is that regardless of whether you
are using XML or annotations, you often need to add
U s ingAnnotationsforORM
@ Entity
c lass Customer {
…
@ Id
@ GeneratedValue
p rivate long id;
U sing XML for ORM
<hibernate-mapping
default-access=“fi eld”>
<class name=“Customer”>
<id name=“id”>
<generator class=“native” />
</id>
@Version
private long version ;
<version name=“version”/>
<property name=“name”/>
@OneToMany
private Set<Account> accounts;
…
}
FIG 2
<set name=“accounts”>
<key/>
<one-to-many class=“Account”/>
</set>
…
</class>
…
</hibernate-mapping>