This way of abstracting database access is very powerful but it does have its drawbacks. For example:
It’s Time Consuming - Where you may have written a query in a few minutes using the old fashioned way, it can take quite a bit of time to write all the needed objects to properly abstract your database access.
It’s Verbose - A typical query is only a few lines. However, when you’re writing components to manage those queries there is a lot of extra code which needs to be written.
It’s Repetitive (and therefore bug-prone) - Almost all of the objects of a particular type end up being very similar when you’re abstracting your database access. For instance, the only major differences between an Address DAO and a Car DAO would be the name of the table and the columns. This level of repetitive coding leads to a copy-paste-and-edit approach which is likely to manifest subtle bugs in your application. Even if each object is manually typed out there’s a good chance that bugs will slip through.