it in the id field. The version field is configured to store a Hibernate-main-tained 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 fields to store the primary key and a version number. The primary-key field is usually required by Hibernate or by a domain object’s clients. The version number is used for optimistic locking. The trouble with these fields, however, is that typically the application’s business logic does not require them. They

must be added to every domain class solely to support persistence.

O/R mapping in GORM. Grails relies heavily on Convention over Configuration when defining ORM. It automatically treats classes in the grails app/ domain directory as being persistent. GORM automatically persists the properties of each class. It defaults table and column names from the class and property names. GORM also adds primary-key and version-number properties to each class.

The following is an example domain class. The Customer class has a field called name. Also, because this field has default visibility, Groovy automatically defines the name property by defining getName() and setName() methods.

 

class Customer {

String name }

you must write code to do this when using vanilla Hibernate.

GORM also makes it easy to map relationships by using static properties to supply metadata in a similar fashion to annotations in other languages. For example, the static property hasMany defines the one-to-many relationships for a domain class. The value of the hasMany property is a map. Each map entry defines a one-to-many relationship: its key is the name of the property that stores the collection, and its value is the class of the collection elements. For each one-to-many relationship GORM adds a property to store the collection of objects, as well as methods for maintaining the relationship.

The following is an example of how to map a one-to-many relationship between the Customer class and the Account class.

GORM automatically maps the Customer class to the customer table and maps the name property to the name column. GORM adds an id property to the class and maps it to a primary-key column called id. It also adds a version property and maps it to a version column. Unlike a traditional ORM framework, GORM requires very little configuration, provided that the database schema matches the defaults.

Another nice feature of GORM is that it will maintain creation and last updated times for domain model classes. You simply have to define lastUp-dated and dateCreated properties on your classes, and GORM will automatically update them. In comparison,

class Customer { static hasMany = [accounts : Account]

}

 

class Account { static belongsTo = Customer

Customer customer }

figure 3.

(a)

Long pk = …

Session session = sessionFactory.getCurrentSession()

Account account = (Account) session.get( Account.class, pk)

(b)

interface AccountDao {

Account get(long accountId);


}
class AccountDaoImpl implements AccountDao {
public Account get(long accountId) {
Session session = sessionFactory.getCurrentSession()
return (Account) session.get( Account.class, pk)
}
}

The collection of accounts is stored in a property called accounts, which GORM adds to the Customer class at runtime. The relationship is mapped using a foreign key called customer _ id in the account table. The belongsTo property specifies that a Customer owns the account and it should be deleted if the customer is deleted.

GORM also dynamically defines a couple of methods for managing this relationship. The addToAccounts() method adds an account to the collection, and the removeFromAccounts() method removes an account. These methods also maintain the inverse relationship from Account to Customer. By automatically defining these methods, which would otherwise have to be written by hand, GORM simplifies the code and makes it less error prone.

Configuring the mapping. CoC reduces the amount of configuration that is required. Sometimes, however, you need to specify some aspects of the ORM. For example, table or column

 

APriL2009 | voL. 53 | no. 4 | communicAtionS of the Acm

51

References:

http://Customer.name

Archives