I use DAOs, and an additional level (persistent services) and the more I use them, the more convinced of their utility.
My DAOs are classes that encapsulate all of the single-table persistency operations for my ORM. That is to say that they implement the save/update/delete methods and the finder methods. They have an ORM EntityManager injected into them, and they are the layer in which all of the query language statements are defined and used.
This makes it easy to locate and
test primitive persistency operations. In particular, I can set up and unit-test the query language-based functions, which is very important, since QL is interpreted at run-time and there are lots of ways to create QL that look OK, but fail when used, because they refer to mis-spelled object model property names, properties that don't exist in the schema for one reason or another (renamed or deleted), and joins that can't join. And, for that matter, queries that return incorrect results.
As I said, I use another tier as well. In this tier I have my business-oriented persistency logic. The methods in these classes deal with interrelated tables all being manipulated under a single database transaction. They invoke DAOs to do their dirty work, but the business of keeping the related objects properly related is theirs, as is any last-minute validation that can only be done when you see the table working set as a unit. To keep things clean, they echo DAOs when simpler operations are required so that the actual non-transactional business layer (and all higher layers) never see the DAOs directly.
By employing this separation of concerns I can do persistent data management cleanly and reliably and I'll always know where to look for a given functionality.