Tags

,


In this post, I wish to share my cribs on how ORM (Object Relational Mapping) tools get abused by naive developers.
The impact is such that one tends to think something is perhaps not right with ORMs.

Object Relational Mapping tools (ORM) map the Object world on to the RDBMS world.
This is a huge productivity benefit. OO developers are comfortable with the notion of Objects and dealing with objects throughout makes it all the more easier. Popular ORM implementations (in the Java world) are Hibernate, iBatis and TopLink.

The single most drawback I see with ORM in the hands of unseasoned developers is that “ORM cultivates in them a disregard for databases and DB concepts“. This isn’t an issue with ORM per se. It is the unseasoned developer who is to be blamed and all. Fine … But then, it results in badly written applications whose performance suck.

ORM’s treat a row in the database as an object (more or less). It is indeed a huge productivity gain for developers to work with objects without bothering about how it came all the way from database. Whereas there is indeed a productivity gain, the down side is the developer’s insensitivity towards the database concepts.

For example, The specification document reads, “…Get all the orders for the given customer. For each order, set the is_delivered flag to TRUE”.

The unseasoned developer translates the specification faithfully in this way

Collection myorders = OrderDAO.findbyID(“customerID”);
for (order : myorders){
order.setIsDelivered(“TRUE”);
order.save();
}

Let us look at the above trivial code from a database perspective.

Collection myorders = OrderDAO.findbyID(“someID”);

This results in the Query like “SELECT * FROM ORDERS WHERE CUSTID = ?”

Inside the loop, the followign statments
order.setIsDelivered(“TRUE”);
order.save();
translate to
UPDATE ORDER SET IS_DELV=1 WHERE ORDERID = ?

Please note that the UPDATE statement is executed for EACH order.

Instead, what we actually need is

“UPDATE ORDER SET IS_DELV=1 WHERE CUSTID = ?”

If there are N orders for a Customer, then N+1 Queries are executed in place of just One Query.

The fundamental difference between a language like Java and SQL is that while Java is a programming language
SQL is a DECLARATIVE language. SQL tells what needs to be done and omits the how. Java programming is mostly about the how.

Another classic example is … the specification reads “If there are records meeting this criteria, then update them with this value…”

The unseasoned ORM-er would do it this way

Collection myorders = order.findbyParams(x,y,z,p,q,r);
if (myorders.size > 0){
order.setSomeParam(somevalue);
order.save();
}

I cannot blame ORM for such abuse of SQL. Even developers using plain jdbc (and no ORM)
would translate the above spec as

select count(*) from ORDER WHERE
if (rowcount > 0) {
//perform the update
}

The SQL which is actually needed is

UPDATE ORDER SET SOME_PARAM = :somevalue WHERE

Obviously, if the criteria matches no records, the update would not happen anyway.

ORMs make it easier for naive developers to overlook the basics of databases.
ORM works best at the hands of those who have solid DB fundamentals and use ORM the right way.

The issues get magnified when say, 5000 users are connected, and thus there is a potential for each query to be fired 5000 times ! This means, a single query that is found to be unnecessary, amounts to firing 5000 queries. What a colossal waste of resources. Add to this any missing index etc and the problem gets compounded.

Also ORMs prevent the naive developer from appreciating joins – both complex and simple.
ORMs make it easier for developers to follow the specifications to the dot without any database considerations.

For example, A specifcation reads

“Get the f_id from Table1. Using this query on Table2 to obtain px_y. Use px_y from Table3 to get the m_imp_data.”

The ORM savvy developer faithfully follows the specifications.

String str_f_id = Table1DAO.find(“someid”).getfid();
String str_px_y = Table2DAO.findByBlah(str_f_id).getpxy();
String str_imp_data = Table3.DAO.findByBlah(str_px_y).getimpdata();

Well, as I said before, a naive developer using plain jdbc could as well do the same

String Qry1 = “select f_id from Table1 where blahID = ?”
String Qry2 = “select px_y from Table2 where x_f_id = ?”
String Qry3 = “select m_imp_data from Table3 where x_px_y = ?”

But the point is that ORMs make it a lot easier as the developer is out of touch with SQL (almost).
What is needed here is a simple inner join. You can read more about Joins here.

In a future post, I shall provide examples on the right usage of ORM and how ORM and plain jdbc should co-exist for better performance of the application.

Advertisements