There's a better way: data mapping. It's a pattern first described by Martin Fowler that relies on a discrete persistence layer to translate application domain objects into relational records. Data mappers provide much more convenience than raw queries while avoiding many of the problems and bad habits O/RMs encourage: dual data models, complex state management, inattention to schema design.
The oldest data mapper implementation I'm aware of is MyBatis (formerly iBatis) for Java; I was using that back in the early-mid 2000s. My own project, Massive.js, also operates in this style.
Does ActiveRecord count as a data mapper? It seems to meet some of the criteria.
Interesting. Does that mean you manually need to implement a Mapper for every entity?
It can, but that's kind of doing it the hard way. iBatis/MyBatis, for example, used to require a lot of configuration -- you'd write your own XML mapping which translates columns in each query result to their corresponding class fields, and write SQL which inserts, updates, or deletes records in tables based on object properties (I am given to understand they've automated most of the basic one-table-at-a-time CRUD since I last used it). What's interesting about doing this is that you're not restricted to a one-to-one table:class mapping: you can source a domain object from a complex view, and decompose it into its constituent tables when you persist. It's immensely powerful and lets you do some really elegant things with your schema design.
It sounds quite interesting, do you have further resources that one can look into to learn more on this.
Fowler has a book about enterprise patterns in general including the data mapper, although I have to admit I haven't read it. Other than that, your best bet is probably to learn by doing. Massive has an interactive REPL and extensive documentation if you do Node, or you could look at some of the other implementations from the Wikipedia article.
Thanks for the pointes Dian, I really appreciate it.
That's the pattern I've been using for many years.
If your schema can be persisted with an ORM, I guess it means that it's so simple and straightforward that you don't need no ORM.
I usually call them data stores instead of mappers, but I'm a huge fan of this pattern.
I want to write objects that make sense given the problem I'm solving, and all I want my domain layer to know about the persistence layer is "I can put stuff there and get it back later."
We're a place where coders share, stay up-to-date and grow their careers.
We strive for transparency and don't collect excess data.