Persistence Strategies: DAO (Data Access Objects) and ORM (Object-Relational Mapping) – Part 2
Article 2: DAO – Data Access Objects
Some time has passed since my first posting. My investigation on persistence originally focused on DAOs. I was looking for a relatively simple way to persist data, without a full-blown persistence solution (like Hibernate, OJB, or iBatis). Before I get too far ahead, a definition of DAOs are needed.
Data Access Objects (DAOs) are a design pattern, popularized by Java, that essentially separates your presentation code from your persistence layer. Or, the code that is responsible for reading/writing your objects to and from disk/database/memory. DAOs provide a layer of abstraction for basic CRUD (Create, Read/Retrieve, Update, and Delete) operations.
After some experimenting, I quickly discovered 2 key points:
1) DAOs work great by themselves for simple requirements: 1 object = 1 table
2) DAOs and other persistence solutions are by no means mutually exclusive. In fact, they really should be used in conjunction wherever possible.
On the first point, let’s use the example of having both Customer and Order objects. In this scenario, the relationship between Customer and Order is 1 to many, m:n (A given customer can have multiple orders). And, to make things more complex, this association can be made bidirectional. Meaning, that the Order object may need to make a reference to the Customer (possibly via a getCustomer() method).
While experimenting, I discovered a great (and free) online DAO generator (http://titaniclinux.net/daogen/). DAOs are a great candidate for automatic generation since there is a great deal of replication between each implementation. In this case, DAOgen essentially prompts you to provide a table name and corresponding columns, along with a class name and corresponding properties. When it is done, your class and DAO will be generated for you. In the case of Customer, the following methods were generated for the DAO:
All CRUD methods are here and the SQL queries are dynamically generated and placed inside the DAO implementation. This system works great when dealing with single objects. But, in the Customer->Order relationship, some manual coding is needed in the Customer DAO to instantiate a Order DAO and load all Orders for the given Customer. This is certainly doable, but probably does not scale well for a more complex system. Especially one that has a deep object graph, and is hierarchical in nature.
On the second point, the key thing to keep in mind is that DAOs are really solving a different problem than persistence, or ORM (object relational mapping) itself. DAOs are really one strategy for implementing a generic data access layer. While ORM, is strictly responsible for mapping your objects to your database (directly to tables themselves or SQL mapping). Together, both the DAL (Data Access Layer) and ORM form a total persistence framework.
While researching DAOs, I’ve put together a list of good sites on the topic. Along with some links that focus on general design patterns, best practices, business object, and data transfer objects. I posted this info on the iBatis mailing list the other week. This has now been incorporate into their Wiki, under “Where can I get more information about Data Access Objects“. Here is the original list, along with some additional links.
Data Access Object (DAO) J2EE Pattern
Transfer Object (DTO) J2EE Pattern
Protecting the Domain Model
General Design with BO’s, DTO’s and DAO’s
Using BeanUtils to avoid duplication between DTOs and BOs
One big Service class or several small classes?
Custom-Grained Data Transfer Objects
Dynamically generate DTOs with DynaBeans
The final article will focus on some popular open source persistence frameworks.