Understanding Object-to-Relational Mapping Frameworks

   

When you begin developing applications using JDBC, you will want to pay close attention to the design. In the previous chapter, several examples were used that persisted Java objects to a relational database. The knowledge of how to store the objects in the database was placed either in a method or in the class itself. In some cases, SQL commands were added to Insert or Update data in the database. Although using SQL directly to interact with the database will almost always work, it can become a maintenance nightmare. Although these approaches worked in the simple examples that were presented in this and the previous chapter, there are issues with both approaches, especially for larger real-world applications.

It's true that for some applications, using SQL directly is probably a satisfactory approach. For some small applications, you can argue that maintenance of the SQL will not be an issue. Some, on the other hand, might argue that you never want to have the knowledge of SQL commands in your business objects. The point is that there should be some sort of "Layered" design used in which your business objects contain nothing but pure business logic and the knowledge of how to persist the objects resides in a data layer or database-mapping layer.

This data layer can take the form of other objects or maybe something lighter that is used at runtime by the business objects; the business objects can delegate the persistence to this data layer.

The issues with performing SQL directly in the business objects revolve mainly around the problem of software maintenance and object-oriented design. The question is how do you design a Java database application in which the system knows how to persist the Java objects in an application without the objects having too much knowledge about which datastore they are being persisted to? This was referred to earlier as decoupling the application from a specific database or implementation.

For example, what if you have an application with Java objects that know how to read and write their state to the database. Suppose further that the SQL to read and write the objects was located throughout your Java objects. What happens when the schema changes? It can become difficult to track down the correct places that need to change along with the schema. Remember back in the previous JDBC chapter when you had to switch to the JDBC-ODBC Bridge? Because the database configuration information was isolated from the classes, it made it easy to change the configuration. In fact, that configuration information could have been read in from an XML file and used at runtime. In that case, all you would have had to do is edit a text file and no software changes would have been necessary. That's the ultimate goal here ”to reduce the software changes that are necessary when the underlying database configuration changes whether the change is the JDBC URL, the database schema, or even the database vendor.

One way to fix this problem might be to always keep the SQL inside the class that will be using it. For example, what if you have a class called Employee and this class contains all the SQL that it needs to persist itself to some datastore? When the underlying schema changes for this class, you would know where to go to fix the SQL. This helps the problem a little. The modifications would always need to be made in the class or classes that are directly affected by the database changes. There still is a problem with this solution, however. Any time the column names or fields change, you must recompile Java code. In some cases, this might be okay because, if there are new fields, you probably need to add the attributes to the Java class anyway. What if just one of the column names changes or the table name changes? You must change Java code and then recompile. The problem is that the changes usually have cascading effects. So, a single database change can turn into several software changes.

As you can see, there are various ways that you can keep abstracting out the database knowledge and move it further and further away from the actual Java code. This leads to the discussion of Object-to-Relational Mapping (ORM) frameworks. Whether you are designing a small single- user database application or a large multi-client application, one issue will always come up during design, "How are you going to access the database with the Java objects?" You need a strategy for mapping the object model to the relational model in order for Java objects to become persistent to the database. The problem is that you need to take an object model and flatten it out for the relational database to deal with. You need to do this in a manner that will be relatively easy to maintain and scalable if the number of database calls becomes high.

ORM frameworks are like any other framework in the Java world. They provide a set of classes that can be used and extended in your Java applications. ORM frameworks are specific to giving the Java objects access to a database in a way that makes it easier for the developer to interact with the database. In most cases, the developer is interacting with an API above JDBC. So it's usually even more object oriented. For example, to save an object instance of Employee, all you might have to do is something like this:

 Employee newEmployee = new Employee(); newEmployee.setFirstName( "Linda" ); newEmployee.setLastName( "Lee" ); // Set some more required fields newEmployee.save(); 

This code is a little fictitious, but there are some frameworks that do it this way. You don't interact with JDBC, but rather a higher-level API that uses JDBC in it. The details of where the attributes of Employee go in the database are taken care of through the mapping that was done during design. The framework classes could also handle issues such as using the native sequencing of the database to provide a new unique identifier (UID) for the Employee record. Also, there's the issue of objects that reference other objects. Suppose the Employee class referenced an Address and Phone Number class. The framework could handle saving these child classes when the Employee was saved. It could also update the foreign keys from the Employee table to the Address and Phone Number table. Here's what the code might look like:

 Employee newEmployee = new Employee(); newEmployee.setFirstName( "Linda" ); newEmployee.setLastName( "Lee" ); // Set some more required fields for Employee // Create and set the address for this employee Address addr = new Address( "3275 Main", "Snellville", "GA" ); NewEmployee.addAddress( addr ); // Create and set a phone number object PhoneNumber phone = new PhoneNumber( "770", "123-4567", "x1234" ); NewEmployee.addPhone( phone ); // Save the employee which also saves the children objects automatically newEmployee.save(); 

There are many Java ORM frameworks available. Some are open -source projects that are available for free, and then there are some that are downright expensive. Not all of them are created equal either. When evaluating them, you have to look at the list of features that each provides and do the usual buy-versus-build analysis on what you get with the framework against what it would cost for you to build in that functionality. There are too many features to list all of them here, but here's a brief list of Java ORM frameworks and where to find out more about them:

Name Location
TOPLink http://www.webgain.com
CocoBase http://www.thoughtinc.com
Poet http://www.thoughtinc.com
Java Blend http://www.sun.com/software/javablend

This list is by no means complete. Each vendor provides different features and functionality.

As stated earlier, ORM deals with mapping Objects to relational databases. Unless you are using an Object database or some of the newer features of databases such as Oracle, objects need to be flattened out before they can be persisted into a relational database. Flattening means taking all the object's attributes and storing them horizontally into a database record. You also need to maintain the references an object has to other objects.

When attempting to map classes to a database, there are several ways this mapping can be done. First, a class can map directly to a table by itself. Secondly, it can be mapped to multiple tables. Or several classes can be mapped to a single table. This really depends on the physical design that you are mapping to. The process usually involves performing a good logical object-oriented design, without any thought of what the physical will be. This is done based on good OO analysis and design methods . Then, usually a data architect who understands how logical and efficient physical models should be built, goes off and designs the database schema. Finally, the two worlds need to be combined so that the objects can be persisted in the physical and then be reconstituted back into the object model later.

There are many things to consider, and it does get a little complicated depending on the size and complexity of the design. Some things are easy to figure out, such as mapping attributes and columns . Other areas are not easy, such as inheritance and aggregate objects. Each ORM vendor supports these a little differently, so make sure when choosing a vendor that it supports all the design features you need. For example, does the vendor's ORM framework support one-to-one, one-to-many, and many-to-many relationships? Does it have some kind of easy-to-use GUI builder to help with the mappings, which can get confusing? Even more serious issues should be considered , such as whether the ORM provides connection pooling and caching. It really all depends on what you are looking for in an ORM and how much money and time you have to invest in choosing one. The newsgroups are a great source of information for ORM frameworks because many people have used them or are in the process of evaluating them. So, many questions can be answered by reading the various newsgroups.

   


Special Edition Using Java 2 Standard Edition
Special Edition Using Java 2, Standard Edition (Special Edition Using...)
ISBN: 0789724685
EAN: 2147483647
Year: 1999
Pages: 353

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net