The cure for RoR Active Record and transactions 📎
It seems to be still a little be confusion about the possible inconsistencies using ActiveRecord. I got another good example from Behi (thank you):
---
Suppose that you have loaded an object from the database using an ORM tool and
have modified one of its fields:
Employee e = ORM.findEmployee(1);
e.setSalary(e.getSalary() * 1.1);
Now in the same transaction, suppose you have loaded the same employee once
again, this time modifing another of its fields:
Employee e2 = ORM.findEmployee(1);
e2.setBonus(5000.0);
Now at the end of the transaction you save e and e2:
ORM.save(e);
ORM.save(e2);
Now depending on the ORM you use, the change to the salary field of the
employee might be lost! (In RoR, it's lost, In EJB 3 is not lost)
--
The solution for this problem provides the IdentityMap pattern, which is well explained by Martin Fowler. This pattern ensures, that you only see one and only instance of a persistent object in a transaction. It is good for read access, but writing is more problematic. In case you update a table or delete data in the table you should also update or at least delete the instances in the IdentityMap which is not easy to realize (the IdentityMap should be then able to understand the SQL and behave the same way like the database).
I haven't such problems with RoR, but in Java EE space with some home-grown OR-mappers. The procedure was always the same:
- Developers built an own persistence framework (because it was easier, than JavaEE :-))
- Inconsistencies occured.
- The framework was replaced by hibernate, cmp 2.0 or jdo
Sometimes is Java EE easy - comparing it to the alternatives :-)