The Beauty of Object Relational Mapping

December 30th, 2008 § 5

I wanted to blog about this issue a while ago, however I didn’t get a chance until now, thanks to Dreamhost. You see, I rely on subversion (hosted on my dreamhost account) for my revision control and my repositories are unaccessible for the second time in 9 days! With the exception of this latest issue I’ve been happy with dreamhost. Update: they fixed this issue about 16 hours after I contacted them.

The Problem

Now, getting back (or starting) on topic. A long time ago (dinosaurs used to roam the streets then) I was faced with the issue of designing Object Oriented Code (OOC, hmm haven’t seen that acronym before. Yeah, I just made it up on the spot :) . Yah, I’m that good). Normally we’re taught that in OOP the classes you create should represent (or go as close to it as possible) real world objects (containing information in fields and defining possible action in the methods). For example, a car class could have model, manufacturer, and owner as fields and driveTo(…) as a method. This is all fine and dandy for little school assignments where your objects are all created in the code and nothing is stored on databases or even flat files. However as soon as you start thinking about using a database a problem arises. When an object is created and manipulated and all that fun stuff, it needs to live somewhere after the program stops executing (can’t live on RAM, obviously) so a database is often needed to store the existing objects. In other words these fields (or the state of an object needs to be stored in a database). So, long ago, I was working on a project and needed to represent members (of a website). I had come up with the database and fields for my class (see Figure 1).

Figure 1 - Representation of my class and the DB table of it

Figure 1 - Representation of my class and the database table for it. Don't pick on my UML diagram as I still don't know how to properly make one. I make them so I understand them, just like my code :)

The table columns simply mirrored the fields of my member class and there were methods to retrieve member information such as getAge(), etc. and I could nicely do this (PHP):

$newMember = new member(5)
echo $newMember->getAge()

Now that looks okay, except for one problem. Problem is that every time you have a new class or object you have to:

  • create the database table to represent that object
  • create the class in code (using language of choice, of course)
  • and define methods to link the two, including the necessary SQL

That’s a lot of work.

One Solution

My friend Milot, on his blog post Code Structure and OOP Concepts Implementation, talks about one method of easing this pain. He proposes three layers:

  • DataAccess layer–deals with querying the database and making the results available to the object
  • DataTransferObjects layer–like the member class in Figure 1
  • and the GUI layer–can interact directly with the object we are dealing with and doesn’t have to worry about the database

This method might work for some people but my main criticism for it was that code duplication would have to happen much like my initial solution (this was one of the problems with the initial solution) and second, the resulting code in the GUI methods wasn’t very object-oriented looking:

Products p = new Products() { Name = txtName.Text, ... };
ProductsOperations products_op = new ProductsOperations();
bool isRegistered = products_op.Register(p);

In addition, I don’t find that easy to read. What I’d rather have is something like this:

Products p = new Products() { Name = txtName.Text, ... };
bool isRegistered = p.isRegistered(); // this is more like it :)

The best solution

It turns out this problem has existed for a while (I guess I don’t get credit for finding the problem, let alone the solution!). The nice solution that will allow you to just relax a bit more (see Figure 2 for a demonstration) is Object-relational mapping (or ORM). 

Figure 2 - Relax.

Figure 2 - Relax.

ORM simply maps your class (or object, if you will) to a database table(s) and if the ORM system you’re dealing with is powerful enough, it’ll handle even the relationships between your objects! Sweet, right? Okay, I’m beginning to sound like a snake oil salesman, so let’s look at Django’s ORM implementation (I looked at some PHP ORMs such as propel and repose but they didn’t seem nearly as nice as Django’s ORM implementation).

In Django you first define a model (this is all python):

from django.db import models

class Member(models.Model):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)


 
Then you simply execute this command: python manage.py syncdb and Django creates all the necessary tables for the database that you’re running (could be sqlite, MySQL, or PostgreSQL).

Once Django creates the database, you’ll be able to use the Model in normal python code and not even worry about the database communication and so on. The ORM even protects you from SQL injection attacks as you won’t be executing SQL commands directly.

So, now we have this:

newMember = Member("John", "Smith")
newMember.save()
# This creates a person with first name John and last name Smith. It's that simple.

or for Milot’s problem:

#define the model
from django.db import models

class Product(models.Model):
    # The ID is auto-generated as the primary key,
    # so we don't have to create it.
    name = models.CharField(max_length=30)
    description = models.CharField(max_length=100)
    price = price = models.FloatField()

then we can access Product information like this:


newProduct = Product("Audio R8", "Only the awesomest car in the World!", 110000.00)
newProduct.save()

#then we could retrieve the recored we just created
sameProduct = Product.objects.get(name="Audio R8")

I should mention that Django is a python based Web framework, or as its developers claim The Web framework for perfectionists with deadlines. Who am I to argue :)

Thanks for reading. Your comments or corrections are much appreciated.

  • Share/Bookmark

XML Indentor

December 18th, 2008 § 0

I was playing around with an Amazon API and needed a way to indent the XML it was returning in order to make any sense of it.

A google search came up with this awesome tool. A great thanks goes to Jon Aquino :D .

  • Share/Bookmark

I can’t spell, the browser can’t tell

December 10th, 2008 § 0

I spent about half an hour trying to figure out why this code wouldn’t do what I wanted it to do, which is just create a div element and position it at a specific coordinate in the page:

var contactInfoDiv = document.createElement('div');
m = $(linkStr).positionedOffset();
contactInfoDiv.style.cssText = "background-image: url('{{MEDIA_URL}}images/nav_pointer.png'); width: 29px; height: 16px;"
contactInfoDiv.style.cssText += "position: abolute; top: " + (m.top - 70) + "px; left: " + (m.left - 85) + "px;";

document.body.appendChild(contactInfoDiv);

Don’t know if you caught it or not, but position: abolute is actually supposed to be position: absolute.

Don’t you wish the browser was a bit more unforgiving? So, instead of having my code kinda-work, it would have choked telling me that abolute is not a recognized position, and it would have taken me 5 seconds to resolve the issue, instead of half an hour.

Or maybe, just maybe, I can learn to spell—yeah, not happening.

  • Share/Bookmark

Where am I?

You are currently viewing the archives for December, 2008 at life of a gizmo.