What's Wrong with Object-Relational Mapping

by chromatic

Dave Cross has posted a short series of slides entitled What's Wrong with ORM. Though they're slightly Perl-centric, they discuss weaknesses of many ORM systems of other languages too -- especially not taking advantage of the power of the database.


2006-03-24 01:23:02
Only trouble with some of his points is that he sets the bar for a "database" very high (MySQL STILL doesn't yet qualify) and his suggestion of using the database to influence the code means that down the line your code could be vulnerable to bugs created by changes to the database, even if your program might otherwise be ok with them.
Dave Cross
2006-03-24 02:18:28
I don't think I'm setting the bar for a database very high. I'm talking about features that many databaes have had for years. I don't understand why people would deliberately cripple their system by using inferior tools. I think that MySQL 5 probably meets the criteria. I just prevaricated as I haven't looked at it very closely yet.

And yes, changing the database can potentially introduce bugs in your code. Isn't that true even if you're not generating code from the database? I don't see how this makes that situation worse. And anyway, isn't that why you have tests?

2006-03-24 08:18:47
if you map to views and stored procs then you are less likely to be vulnerable to database changes and porting to a database with a similar feature set is easier. lots of shops have invested in just one database platforms so they don't care. talking about bugs due to changes in the database is a spurious argument. if someone trashes something then yes things will break. if someone drops a table in the database or some permission things will stop working even with the worlds best OR mapping framework. if you don't have the same controls and change management with your database as you do your program you are doomed anyway. having performance fixed EJB code by pushing work into the database i believe that folks should have a more open mind about using different approaches to get the job done rather than being religious about OO or RDBMS.
2006-03-24 08:36:43
again and again O-R mapping tools ends up with rows mapped into objects. consider this case: you have three tables. users, clients, user_client_permission. the third tables is a link table which says whether a user has visibility of the client and what permissions they have (read-only, read-write). the link tables only has rows for user assignments that exists. no row exist if the user has nothing to do with the client. typically with bad O-R mapping you end up having to do your own code to say "given this user object pull up all the user_client_permission objects and if one exists and it is read-write then allow the update to the client". this is bollocks. put in a view which left outer joins users to clients via user_client_permission and if client.id is null use a case statement in the view to set the permission to zero. then have an object user and you call its updateClientMethod have it lazy load from the view which will always pull back a row even with permission zero and store it in a hash map within the user object. that way you have a more encapsulated user class that handles its own destiny. then you are no longer thinking in terms of objects that model database rows (which is no abstraction whatsoever). if the database wants to totally change its table structure on its next release to do permission you simply fix up the database view.
2006-03-24 08:53:11
p.s. a poor O-R mapping tool could make writing the code in quotes trivial but if you profile the database you might be shocked to see what it does (e.g. i have seen O-R code pull back one row back for the user, then one row back for the client, then one row at a time from the link table, look over this set, find the match, then give you the answer). i really have seen that on a live system which *really* did not scale. the fix was as i suggested which is *both* better OO and better RDBMS. poor O-R can be poor at OO and poor at RDBMS.
2006-04-03 00:51:55
Some additional points that were not mentioned in Dave's slides :

  • the ORM usually automatically downloads a given set of columns (or '*'). If you just need one column you loose performance
  • if you join T1, T2, T3 in one single SQL statement, then the ORM does not know how to what kind of class those rows could be mapped
  • ORMs often have trouble to deal with multiple relations between two tables, or with reflexive relations (for ex. parent-child)
  • once your data retrieved from the DB is in memory, you often want to walk through it (for ex. generating XML, Jason, or Data::Dumper output). But this may be hard to do automatically if the ORM enforces strong OO encapsulation and information hiding