My approach has been to auto-generate the DB, rather than the code.
I hope it is good relational normalization. Some OO'ers prefer a bunch of "skinny" tables, and that is uuuuugly and hard to use.
Doing it directly in the DB without an intermediate layer locks you into a specific DB (and vendor).
I am not sure this can be avoided without complicating the code by taking your queries down to the lowest-common denominator and adding a bunch of cluttery wrappers. Plus using an OR-mapper locks you into the OR-mapper tool/vendor. You seem to be trading one lockage for another.