ORM is an anti-pattern
Seems like all you have to do is use ORM once past the “implement a todo app” stage to get to these conclusions.
In summary (TL;DR)
ORM is initially simpler to understand and faster to write than SQL-based model code
Its efficiency in the early stages of any project is adequate
Unfortunately, these advantages disappear as the project increases in complexity: the abstraction breaks down, forcing the dev to use and understand SQL
Entirely anecdotally, I claim that the abstraction of ORM breaks down not for 20% of projects, but close to 100% of them.
Objects are not an adequate way of expressing the results of relational queries.
The inadequacy of the mapping of queries to objects leads to a fundamental inefficiency in ORM-backed applications that is pervasive, distributed, and therefore not easily fixed without abandoning ORM entirely.
Instead of using relational stores and ORM for everything, think more carefully about your design
If your data is object in nature, then use object stores (“NoSQL”). They’ll be much faster than a relational database.
If your data is relational in nature, the overhead of a relational database is worth it.
Encapsulate your relational queries into a Model layer, but design your API to serve the specific data needs of your application; resist the temptation to generalize too far.
OO design cannot represent relational data in an efficient way; this is a fundamental limitation of OO design that ORM cannot fix.
A Groovy Programming book called ORM the Vietnam of Computer Science. I think I’d rather have the problem than the solution.
(Not a whole lot of people agree with me, as witness this discussion). I think ORMs are okay for Rails style apps with application specific data sets especially if the apps are to be client installed on a variety of RDBMS implementations. Maybe not so good for other sorts of data sets, or when writing an app to use a database some other app has created (say, at the end of a data pipeline). I don’t find writing SQL and related de/serializers tedious even in Java, mainly because I wrote a sort-of functional way to do it.