File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
The moose likes OO, Patterns, UML and Refactoring and the fly likes Understanding the DAO Pattern Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Soft Skills this week in the Jobs Discussion forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Understanding the DAO Pattern" Watch "Understanding the DAO Pattern" New topic
Author

Understanding the DAO Pattern

Jaz Chana
Ranch Hand

Joined: Feb 19, 2008
Posts: 34
Hi guys,

I want to understand DAO before I learn something like JPA or Hibernate. I think i'm close to understanding the how, but I need verification to boost my confidence.

I have an example schema consisting of two tables; Sandwich, Ingredients and Nutrition. Sandwich can have multiple Ingredients and each Ingredient can be associated with only one Sandwich. Therefore Sandwich and Ingredient have a one to many relationship.

Thats easy to translate into a DAO pattern;

{code}
class SandwichDTO {
String name;
float sandwichPrice;
List<Ingredients> list;
}

class IngredientDTO {
String name;
float price;
SandwichDTO sandwich;
}

class SandwichDAO {
public SandwichDTO getSandwichWithName(String name);
public List<IngredientDTO> getSandwichIngredients(String name);
}

class IngredientDTO {
getIngredientWithName(String name)
getIngredientForSandwich(SandwichDTO sandwich);
}
{code}

Question 1 Is this correct?

Now Ingredients can have multiple Nutrional values and each type of Nutrional value can be associated with many types of ingredients. This seems to me like a many-to-many relationship and I'm assuming you would use a go-between table to map the relationship, for example;

Ingredient
---
ingredientID(pk)
name
price

Nutrition
---
nutritionID (pk)
name
unit

NutritionalValues
---
nutritionID (fk)
ingredientID (fk)
value

Question 2 In the DAO pattern could this be represented as follows?

{code}
class IngredientDTO {
String name;
float price;
SandwichDTO sandwich;
List<Nutrion>
}

class NutrionDTO {
String name;
String unit;
String value;
List<Ingredients>
}
{code}

Question 3 Is 'value' placed in the NutritionDTO?

Question 4 Would I not bother to put a list of ingredients in the NutritionDTO as I could never see a reason to find all the ingredients associated with a particular nutrition type?wi

I have many more questions if someone is willing to answer. Any help would be a big help.

Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
Jaz Chana wrote:
Thats easy to translate into a DAO pattern;

{code}
class SandwichDTO {
String name;
float sandwichPrice;
List<Ingredients> list;
}

class IngredientDTO {
String name;
float price;
SandwichDTO sandwich;
}

class SandwichDAO {
public SandwichDTO getSandwichWithName(String name);
public List<IngredientDTO> getSandwichIngredients(String name);
}

class IngredientDTO {
getIngredientWithName(String name)
getIngredientForSandwich(SandwichDTO sandwich);
}
{code}

Question 1 Is this correct?


Of course there is not just simply "one correct solution" - and which solution is best will depend a lot on circumstances that aren't touched in your description. But there are a couple of things I'd like to point out about your code:

  • DAOs don't have to work on DTOs - unless the calls to the DAOs are remote calls, it would be preferable if they would return Domain Objects instead of DTOs. See http://martinfowler.com/bliki/LocalDTO.html
  • getSandwichWithName should probably be called getSandwichByName instead
  • I'm curious about the getSandwichIngredients and getIngredientForSandwich methods. First, it sounds to me like they would both do the same thing, so you should get rid of one of them - probably the one on the SandwichDAO. Also, I'd guess that you might not even need that one method - the getSandwich* methods should already populate each sandwich with its ingredients, and that might be all you need. Don't overdesign your DAOs.
  • I also wonder why an ingredient needs to know its sandwich. In general, I'd try to avoid that double linking in an object model, because it can lead to inconsistent object graphs, which can lead to bugs that are hard to debug.


  • Now Ingredients can have multiple Nutrional values and each type of Nutrional value can be associated with many types of ingredients. This seems to me like a many-to-many relationship and I'm assuming you would use a go-between table to map the relationship


    That's quite possible, but should be totally irrelevant to the design of your domain model and DAOs. The DAOs should in fact decouple your object model from the data model used for persistence.

    Question 2 In the DAO pattern could this be represented as follows?

    {code}
    class IngredientDTO {
    String name;
    float price;
    SandwichDTO sandwich;
    List<Nutrion>
    }

    class NutrionDTO {
    String name;
    String unit;
    String value;
    List<Ingredients>
    }
    {code}

    Question 3 Is 'value' placed in the NutritionDTO?


    What would be the consequence of doing that?

    Question 4 Would I not bother to put a list of ingredients in the NutritionDTO as I could never see a reason to find all the ingredients associated with a particular nutrition type?


    And even if there was a reason, there might be a better way to do that (for example query the database via a DAO). As far as I can tell, Nutrition should most likely be a simple immutable Value Object, that doesn't know anything about ingredients at all.

    Hope this helps...


    The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
    Jaz Chana
    Ranch Hand

    Joined: Feb 19, 2008
    Posts: 34
    Thanks for your reply, it is extremely helpful.

    Riiight! Some things you've said have confirmed for me what I believed was true but never had the courage to implement. Your basically saying that a DAO should be designed about the Domain Objects (i.e. the app functionality) as opposed to the DB?

    So my Domain Objects happen to be Sandwich, Ingredient and Nutrition. A Sandwich is composed of many Ingredients and we would like to know the ingredient and price of a Sandwich. Also the names of the sandwich over/under a certain price. An Ingredient has a name and a price and can also have some Nutritional values associated with it. We would like to know the nutritional values of a particular ingredient. Therefore:



    Question1 Is the above correct? It seems to me that the getSandwichWherePrice* methods should really be in the Business Objects. It feels odd to place them here.

    Now say for example I have an Order Domain Object. An order is composed of a list of Sandwiches and the order date. The Domain Object and DAO are defined as;


    Question 2a Firstly the placeOrder method seems like it should go in the BO not in the DAO. But if you do this then you have nothing in your DAO to actually insert the Order into the table. What is the best way to deal with this?
    Question 2b The getOrderByDate method will return an Order object. Will it also populate its nested objects? For example, will it populate the list of Sandwiches, and will it populate the each of the ingredients in each sandwich? How far will the level of nesting go?

    One solution I saw was to pass in a boolean parameter, so get getOrderByDate would look like



    This will populate or not populate the list of sandwiches depending on the boolean value.

    Question 3 How would you determine whether the ingredients of each sandwich get populated? Would that involve passing in more parameters?
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    Jaz Chana wrote:Your basically saying that a DAO should be designed about the Domain Objects (i.e. the app functionality) as opposed to the DB?


    Yes!


    Question1 Is the above correct?


    I assume that you meant to put the getNutritionalValue method on the Ingredient class, not on the DAO. Assuming that, it looks reasonable.


    It seems to me that the getSandwichWherePrice* methods should really be in the Business Objects. It feels odd to place them here.


    Well, that depends a bit on your (performance) requirements. Do you typically want to keep all your sandwiches in memory? Then putting the method on a BO is reasonable. Do you want to do your database do the work of only selecting (and loading) the needed sandwiches (which might be a requirement if you have a lot of them), having this method in the DAO is necessary.

    One way to shield your business logic from this decision (and therefore being more flexible) is to introduce a Repository as another layer of indiraction. For your case, this might easily be overkill, though.

    Now say for example I have an Order Domain Object. An order is composed of a list of Sandwiches and the order date. The Domain Object and DAO are defined as;


    Question 2a Firstly the placeOrder method seems like it should go in the BO not in the DAO. But if you do this then you have nothing in your DAO to actually insert the Order into the table. What is the best way to deal with this?


    A DAO would typically have a save method that takes a new BO and persists it to the storage. Depending on the circumenstance, you might have a separate update method or both combined into one saveOrUpdate method.


    Question 2b The getOrderByDate method will return an Order object. Will it also populate its nested objects? For example, will it populate the list of Sandwiches, and will it populate the each of the ingredients in each sandwich? How far will the level of nesting go?


    How are the requirements? Will populating all the fields (recursively) be a problem?

    Another approach, supported by a number of ORM tools like hibernate, is lazy loading, especially for collections. This approach uses a specific implementation of the collection interfaces that only actually populate the collection from the database once they are accessed.


    Question 3 How would you determine whether the ingredients of each sandwich get populated? Would that involve passing in more parameters?


    Possibly - if you need both versions of the functionality.

    With all those variations, the interface of a DAO can quickly become quite overwhelming. At some point it might make sense to take a look at the Interpreter pattern, to make the DAO interface both more lightweight and flexible. Application of that pattern would allow you to write code such as

    orderDao.loadBy(and(between("orderDate", yesterday, today), equals("customerName", "Preuss")).omit(Ingredients.class));

    Again, for a simple application, implementing this might be heavy overkill. I'd always suggest to start as simple as you can, and refactor to more elaborate patterns when you need them.
    Jaz Chana
    Ranch Hand

    Joined: Feb 19, 2008
    Posts: 34
    Brilliant!!! This is really beginning to make sense now.

    Just one more question and I think i'm there. More confirmations really. Imagine a web app that customers can use to order their sandwiches. They can log on select the ingredients they want and place an order. Now imagine on the other side you have the shop or the admin staff that update the ingredients and look at the orders made. Say, for example, that all the admin staff wanted to do was check the time and price of the orders. Would it be good practice to create two Order domain objects, one for admin and one for customers. For example;



    Would this be an appropriate way to design the classes?
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    I wouldn't do it by default, because it makes the design more complex. And if your solution already supports lazy loading for collections, it looks quite redundant to me. If not, though, it might be that just having one order class leads to performance or memory problems (for example if you have to create reports over a huge amount of orders). In that case, it might make sense to use your solution.
    Jaz Chana
    Ranch Hand

    Joined: Feb 19, 2008
    Posts: 34
    Thanks alot for you help. You've helped me to understand the DAO pattern properly.
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    You're welcome!

    Keep in mind that this is just one man's voice - there might be other people with different opinions on this...
    Jaz Chana
    Ranch Hand

    Joined: Feb 19, 2008
    Posts: 34
    True. I think one important lesson I've learned is that there is no absolute answer, it all depends on the situation. Although design patterns are a good way to implement solutions to common occurring problems they are not an all encompassing solution. As such care must be taken to make sure that you don't overdesign you solution.
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    Jaz Chana wrote:True. I think one important lesson I've learned is that there is no absolute answer, it all depends on the situation. Although design patterns are a good way to implement solutions to common occurring problems they are not an all encompassing solution. As such care must be taken to make sure that you don't overdesign you solution.


    That's quite a good lesson to take away!
    Jimmy Clark
    Ranch Hand

    Joined: Apr 16, 2008
    Posts: 2187
    The Data Access Object design pattern is for handling all things related to accessing data. This includes executing stored procedues of a relational database and extracting data from flat files, CSV files, XML-based files, etc.

    So, there is a bit more to the pattern than just saving/retrieving data of business/domain objects.

    Just my two cents
    Ilja Preuss
    author
    Sheriff

    Joined: Jul 11, 2001
    Posts: 14112
    James, I fully agree. Do you see any conflict between what you said and what has been said before? Just curious...
    Jimmy Clark
    Ranch Hand

    Joined: Apr 16, 2008
    Posts: 2187
    No. My statement provides supplemental information about the design pattern which may help foster a greater understanding of how the pattern is used.
    babusivam ram
    Greenhorn

    Joined: Oct 01, 2013
    Posts: 3
    more here ...

    http://ramj2ee.blogspot.in/2013/08/data-access-object-design-pattern-or.html

    Application business logic often needs domain objects which is persisted in either Database, File System or any other persistence storage. DAO pattern allows you to encapsulate code for performing CRUD operation against persistence from rest of application. Which means any change on persistence logic will not affect other layers of application which is already tested. DAO pattern enables application to cope with any change in database provider or persistence technology.
    James Boswell
    Bartender

    Joined: Nov 09, 2011
    Posts: 1031
        
        5

    As a side note, I don't think it is necessary to adopt naming conventions like OrderBO or OrderDTO. These are usually objects that make up your business/domain model and may well be exposed to clients via some interface. In these cases, just stick with Order.

    In the case of OrderDAO, this is acceptable as such objects are normally internal to your application and the suffix acronym adds meaning to the purpose of the class.
    Jeanne Boyarsky
    author & internet detective
    Marshal

    Joined: May 26, 2003
    Posts: 31054
        
    232

    James Boswell wrote:As a side note, I don't think it is necessary to adopt naming conventions like OrderBO or OrderDTO. These are usually objects that make up your business/domain model and may well be exposed to clients via some interface. In these cases, just stick with Order./quote]
    Agreed. I add DTO if the object isn't a domain object and ONLY exists for data transfer. Maybe it is an object that contains a Customer and five random fields. Or a query object.


    [Blog] [JavaRanch FAQ] [How To Ask Questions The Smart Way] [Book Promos]
    Blogging on Certs: SCEA Part 1, Part 2 & 3, Core Spring 3, OCAJP, OCPJP beta, TOGAF part 1 and part 2
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Understanding the DAO Pattern