Original Source
Scott Davis has delivered the next installment of his Mastering Grails series: Grails and Legacy Databases. On this article he discusses 3 different options offered by Grails to let you work with legacy databases. What good would be to the Java community a framework like Grails if in order to use it you must throw away existing working/legacy code?
The Grails Object Relational Mapping (GORM) API is one of the centerpieces of the Grails Web framework. In “GORM: Funny name, serious technology,” you were introduced to the basics of GORM, including simple one-to-many relationships. Later, in “Many-to-many relationships with a dollop of Ajax,” you used GORM to model increasingly sophisticated class relationships. Now you’ll see how the “ORM” in GORM has the flexibility to deal with table and column names in your legacy databases that don’t follow standard GORM naming conventions.
Scott begins with a sound advice: always backup your data. He then proceeds to show a pair of Groovy scripts tailored to backup/restore the particulars of the sample data used on the article’s application. The scripts skim the surface of what you can do with MarkupBuilder (Groovy to XML) and XMLParser (XML to Groovy), you will find plenty of information about them at the article’s Resources listing. He also notes
Remember that for relationships between tables to work, the primary-key field on the one side of the relationship must match up to the foreign-key field on the many side of the relationship. For example, the value stored in the id column in the airport table must be the same as the value in the arrival_airline_id column in the flight table.
To ensure that the autonumbered id fields get restored to the same value, be sure to drop all tables before you restore them. This resets the autonumbering back to 0 when Grails recreates the tables the next time it starts up.
Importing data to the legacy schema is also done via a Groovy script and XMLParser. Because of the nature of the particular data chosen for this application, namespaces must be taken into account. Again Groovy comes to the rescue, making the job much easier than with regular Java. Scott mentions a possible gotcha after reaching this step:
Now that your legacy table is in place, you should do one last thing: disable the dbCreate variable in grails-app/conf/DataSource.groovy. Recall from “GORM: Funny name, serious technology” that this variable instructs GORM to create the corresponding table behind the scenes if it doesn’t exist, and alter any existing tables to match the Grails domain classes. If you are dealing with legacy tables, you should disable this feature so that GORM won’t disrupt the schema that other applications might be expecting.
It would be nice if you could selectively enable dbCreate for certain tables and disable it for others. Unfortunately, it is a global “all or nothing” setting. In situations in which I have a mix of new and legacy tables, I allow GORM to create the new tables, then turn dbCreate off and import my existing, legacy tables. You can see how having a good backup-and-restore strategy is important in such situations.
On to the main course, Scott describes 3 different options to map legacy schemas to Grails domain classes
- Static mapping blocks - the Grails way, usually chosen when no legacy Java classes exist or when you want to start over.
- Legacy Java classes with HBM files - the compatible way for those that stayed away of EJB.
- EJB3 Annotations with Java classes - the painless EJB3/JPA option, configuration at a minimum.
Probably you have seen the first option before, as it is the simplest, groovier of the three. Similar to how constraints are declared in a regular Grails domain class, you must provide a static mappings closure that defines which table must be used and how columns are mapped to fields. The mapping DSL and the domain facilities are flexible enough, allowing you to define fields that must not be persisted for example.
The other two options are of special interest for developers already invested in either Hibernate or EJB3/JPA. Contrary of what you may think, the complexity of both options is almost non-existent. You just drop Java/HBM files in the correct places, add a shadow Groovy class for each domain class that defines the required constraints (remember that constraints are both used for data validation and view generation), tweak DataSource.groovy (in the case of the JPA annotated option) and that’s it. The article describes each option with full sample code.
Scott closes with the following statement
At this point, mapping your objects to relational databases in Grails should be a breeze. (That’s why they named it GORM, after all.) Once you feel confident that you can easily back up and restore your data, you have a variety of ways of getting Grails to conform to the nonstandard naming conventions in your legacy databases. The static mapping block is the easiest way to accomplish this task because it is the most Grails-like. But if you have legacy Java classes already mapped to your legacy database, there is no sense in reinventing the wheel. Whether you are using HBM files or the newer EJB3 annotations, Grails can take advantage of the work you’ve already done and allow you to move forward to other tasks.
Tags: EJB, Grails, Scott Davis