ORM is ...

Posted 2007. 1. 30. 17:15
ORM is a good solution for legacy databases when the schema
 -- Is highly normalized
 -- Has primary keys
 -- Has foreign key relationships referring to primary keys, not columns

나의 막강한 저항... 그러나 어떠한 것은 받아 들어야 한다는거....
objectA == objectB
objectA.equals(objectB)

이 GAP 이 Relational model에서는 unique identifer column 으로 구분....된다 ( 상속도 있고 다른것도 많지만 )
차이는 이것에서 시작이 된다.

In Part I of "Architecture Dilemmas: O/R Mapping Why/When" I briefly explained what Object/Relational (O/R) Mapping is as well as presented some of the other options available for getting data from a relational database (RDBMS). In Part II, I examine some of the motivations to use O/R mapping and some of the costs and limitations O/R mappers.

The premise of O/R mapping is that you have a focused investment in creating the mapping and that you are free from worrying about the data structure.

This leads to quite a few benefits for using O/R mapping:

  • Clean OO design. Hiding the relational model specifics lets the object model be more cleanly analyzed and applied.
  • Productivity. Simpler code as the object model is free from persistence constraints. Developers can navigate object hierarchies, etc.
  • Separation of concerns and specialization. Let the DB people worry about DB structure and the Object people worry about their OO models.
  • Time savings. The O/R mapping layer saves you from writing the code to persist and retrieve objects. O/R mapping tool vendors claim 20-30% reduction in the code that needs to be written. Writing less code also means less testing.

One problem with O/R mappers is that they usually commit the "Needless Repetition" deadly sin (a.k.a. DRY?"Don't Repeat Yourself"). The table structure as well as their relations are stored both in the DB and in the mapping files used by the O/R mapper. This causes a maintenance problem as you need to ensure that both versions of the meta-data don't get out of sync. Rails (as in Ruby on Rails) partly solves this problem by relying on naming conventions. (Note: You can also override the default mapping.) In other environments, you can use code generation for the mapping file to get a similar effect. Both of these approaches result in limited mapping--which means you are likely to switch to manual mapping so you can benefit from the DB capabilities.

Which brings us to another problem with O/R mappers. Writing these mapping files is a daunting task (unless we are talking about trivial mappings) not to mention that O/R mappers tend to have favorite mappings (e.g., class = table or class hierarchy = table etc.) and trying other mapping are more complicated (if at all possible). This needs to be updated every time you change the DB.

One approach I've been taking recently is to isolate the DB structure from the DB side as well; that is, to add database views that expose the DB to the O/R mapper in simple-to-map structure. which means the mapping is simple and straightforward and the database is free to evolve and adapt as needed. For example, in one project we have set up "self-recording" where each update on the view resulting in an insert on the underlying table(s), while the view always reflects the latest version. Other views or queries can be used to go back in time to an earlier snapshot of the data. The downside of this approach is, of course, the double mapping layer (but at least O/R mapping is simple and relatively stable) hasn't been tested for high-data access load scenarios (as with the projects where it is used don't have such characteristics )

Then there are the queries, which is where a lot of O/R mappers stumble. You either get limited query capabilities or you get performance problems on complicated queries which means that you may need to resort to writing the queries manually (if your O/R mapper supports this)--which is what you were trying to avoid in the first place, not to mention that if your team is already familiar with DB techniques (SQL etc.) There's also the added overhead of learning that new query language. If you do feel comfortable with SQL and you want to take the middle ground you can use iBATis which lets you externalize the SQL into XML.

Note that you probably want to look at O/R mappers that support features like caches, lazy initialization , batch modes etc. to help avid the performance problems mentioned above.

On the next and final post on O/R Mapping I'll recommend when and when not to use O/R mapping.

Posted by Arnon Rotem-Gal-Oz at 06:32 PM  Permalink | Comments

In this first blog on "Architectural Dilemmas," I am going to examine object/relational (O/R) mapping. In Part I, I'll provide some background on the subject; in Part II, I'll present some of my opinions on the topic.

IT systems need persistent storage (unless, of course, the systems are really trivial ). This persistent storage usually comes in the form of a relational database, such as Oracle, Microsoft SQL Server, IBM UDB, and the like. There are several alternatives to RDBMSs; for instance, object-oriented databases (OODBs) db4o, persistent object stores (Prevayler, XML databases, and the like.) However, at least until now these alternatives haven't really caught (maybe I'll discuss why on another post) and the fact is that RDBMSs remain pretty much ubiquitous.

Thus you are faced with the task of getting data from the DB into your business logic. Unfortunately the object model and the relational model are somewhat at odds (what Scott Ambler calls "Impedance Mismatch") which means that a properly designed object model will not have a direct automatic map between objects and tables.

The result of that mismatch means that you need to get the data by using one of the following approaches:

  • Direct data access; not highly recommended. Retrieve/Save by using SQL calls(either dynamic SQL or a stored procedure) whenever needed by the business logic. The reason this is not recommended is that there is no separation between.
  • ata Access Layer (DAL). Have an object (per table) that knows how the tables are constructed. The DAL objects retrieves the data. Sometimes this is combined with Data Transfer Objects (objects with only setters/getters to change the data) to transport data between tiers.
  • ActiveRecord. A class that has the same structure of a table fields. A class instance represents a row in the table and static methods affect the whole table. The class abstracts the SQL needed to actually get to the DB.
  • O/R Mapping. Have a layer that is responsible to bridge the gap between the "proper" object model and the "proper" database model.

There are several variants for each approach and mixes of the approaches; for example, the ActiveRecord implementation in the castle project which builds on Nhibernate, an O/R mapper.

Many implementations (for the various methods) use code generation (there are hundreds of generators you can find many of them ordered by platform at http://www.codegeneration.net). There are implementations that use stored proecdures and there are ones that rely on dynamic SQL. Plus there are few middle-ground approaches like iBatis.

In Part II I will discuss motivations to use O/R mapping (over the other approaches) as well as when not to use O/R mapping.


Want to have your dilemma analyzed? Send your architectural/design dilemmas to ask@rgoarchitects.com.