Data Access Objects (DAOs) are a common design pattern, and recommended by Sun. But the earliest examples of Java DAOs interacted directly with relational databases -- they were, in essence, doing object-relational mapping (ORM). Nowadays, I see DAOs on top of mature ORM frameworks like JDO and Hibernate, and I wonder if that is really a good idea.
I am developing a web service using JDO as the persistence layer, and am considering whether or not to introduce DAOs. I foresee a problem when dealing with a particular class which contains a map of other objects:
public class Book {
// Book description in various languages, indexed by ISO language codes
private Map<String,BookDescription> descriptions;
}
JDO is clever enough to map this to a foreign key constraint between the "BOOKS" and "BOOKDESCRIPTIONS" tables. It transparently loads the BookDescription objects (using lazy loading, I believe), and persists them when the Book object is persisted.
If I was to introduce a "data access layer" and write a class like BookDao, and encapsulate all the JDO code within this, then wouldn't this JDO's transparent loading of the child objects be circumventing the data access layer? For consistency, shouldn't all the BookDescription objects be loaded and persisted via some BookDescriptionDao object (or BookDao.loadDescription method)? Yet refactoring in that way would make manipulating the model needlessly complicated.
So my question is, what's wrong with calling JDO (or Hibernate, or whatever ORM you fancy) directly in the business layer? Its syntax is already quite concise, and it is datastore-agnostic. What is the advantage, if any, of encapsulating it in Data Access Objects?
You make some points. But I nevertheless use a Dao layer, here's why:
Database accesses are calls to a remote system. In all such cases (also web-service, ajax etc...), the granularity of interaction need to be big enough. Many tiny calls would kill performance. This performance necessity requires often a different view of the system, or layer (here, the Dao layer).
Sometimes, your persistence operation is only to load/save/delete an object. One unique Dao (or a superclass ; consider Generics) can be responsible for this, so you don't have to code these methods again and again.
But often, you also have specific needs, like running a specific request that is not automatically created by the ORM. There, you code your specific need with a specific Dao method (reuse is often possible).
Having regular and specific needs in the same layer allow for reuse (for example, interception can ensure that a database connection is open/commited when needed).