More DAO Confusion

If you are not familiar with this pattern, it is outlined here: http://java.sun.com/blueprints/corej2eepatterns/Patterns/DataAccessObject.html

I have read through it and even begun to implement it, but am running across some concerns. I would like to know if these concerns are due to a misunderstanding of the DAO pattern or just a problem with the pattern itself.

Let's use a simple example of a Person who has Addresses. And let's say your code needs to retrieve a person, and then later, lazily, needs to retrieve this person's addresses. How does DAO suggest you do this?

The first part, retrieving a Person is straightforward. You retrieve a PostgresPersonDAO (for example), and call the method "getPerson()" passing it along any query information necessary. It returns a plain 'ol Person object (transfer object), with all the attributes of that person.

The second part, however, confuses me. I have a person object. It seems like the most basic relational thing I'd want to do now is call myPerson.getAddresses() to return a list of addresses. In order to implement this method however, now my DAO code needs to be sprinkled into my simple Person object. Is that right? Does that break the pattern? Can the transfer object also act as a DAO client?

if this is the case, your DAO will have "instance methods", meaning they ACT ON an instance of Person, but these methods must take in a Person, since DAOs carry no state:

public List getAddresses(Person),

publicvoid save(Person)

However, they also carry more "static" style getter methods, meaning they return an instance of Person, but do not require an instance of Person:

public Person getPersonByPhoneNumber(String num);

public Person getPersonByName(String name);

Perhaps I am just confirming my understanding of this pattern and that really there is no distinction here. But also however, it often makes me think that Person should extend from a DAO that have access to Person's internals (that sounds bad), so that the "instance"-style methods, are really, in actuality, instance methods.

DAO experts, or interested reads, any thoughts on this would be much appreciated.

[2388 byte] By [nootcha] at [2007-10-2 15:47:33]
# 1

> I have read through it and even begun to implement

> it, but am running across some concerns. I would like

> to know if these concerns are due to a

> misunderstanding of the DAO pattern or just a problem

> with the pattern itself.

>

> Let's use a simple example of a Person who has

> Addresses. And let's say your code needs to retrieve

> a person, and then later, lazily, needs to retrieve

> this person's addresses. How does DAO suggest you do

> this?

DAO says nothing about it. You're right.

That's an implementation detail. DAO is usually expressed as an interface, so there's no guidance that way.

Your Person would have to hang onto the primary key of the Address and then access the value in the getAddress() method if the value was null.

> The first part, retrieving a Person is

> straightforward. You retrieve a PostgresPersonDAO

> (for example), and call the method "getPerson()"

> passing it along any query information necessary. It

> returns a plain 'ol Person object (transfer object),

> with all the attributes of that person.

>

> The second part, however, confuses me. I have a

> person object. It seems like the most basic

> relational thing I'd want to do now is call

> myPerson.getAddresses() to return a list of

> addresses. In order to implement this method however,

> now my DAO code needs to be sprinkled into my simple

> Person object. Is that right? Does that break the

> pattern? Can the transfer object also act as a DAO

> client?

There's nothing stopping the Person object from being a client of the Address DAO. I'd have either a single Address or a List of Addresses that I'd let a member Address DAO get for me in the get method for the Address member(s).

> if this is the case, your DAO will have "instance

> methods", meaning they ACT ON an instance of Person,

> but these methods must take in a Person, since DAOs

> carry no state:

>

> > public List getAddresses(Person),

> public void save(Person)

>

I don't agree with that getAddresses() method. The lazy loading idea makes more sense to me.

>

> However, they also carry more "static" style getter

> methods, meaning they return an instance of Person,

> but do not require an instance of Person:

>

> > public Person getPersonByPhoneNumber(String num);

> public Person getPersonByName(String name);

>

I think of these as find methods. I'd write a Person DAO like this:

package persistence;

public class PersonDAO

{

public Person find(long id);

public Person find(Phone phoneNumber);

public Person find(String lastName, String firstName);

public Person find(String ssn);

public void saveOrUpdate(Person p);

public void delete(Person p);

}

> Perhaps I am just confirming my understanding of this

> pattern and that really there is no distinction here.

> But also however, it often makes me think that Person

> should extend from a DAO that have access to Person's

> internals (that sounds bad), so that the

> "instance"-style methods, are really, in actuality,

> instance methods.

No, I would not have a Person extend a DAO. It doesn't satisfy the IS-A test.

> DAO experts, or interested reads, any thoughts on

> this would be much appreciated.

You're asking a subtle question. It's a good one.

If you write your persistence layer in JDBC you have to worry about all this stuff yourself. If you use a framework like Hibernate it takes care of the lazy loading and caching for you. Those are two of the best reasons for thinking about Hibernate.

But the DAO should always start with an interface. Then you can have your JDBC implementation, a Hibernate implementation, an iBatis implementation, etc.

%

duffymoa at 2007-7-13 15:47:47 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

> If you are not familiar with this pattern, it is

> outlined here:

> http://java.sun.com/blueprints/corej2eepatterns/Patter

> ns/DataAccessObject.html

>

> I have read through it and even begun to implement

> it, but am running across some concerns. I would like

> to know if these concerns are due to a

> misunderstanding of the DAO pattern or just a problem

> with the pattern itself.

>

I personally find DAO very similar to Martin Fowlers Data Mapper. However at the same time i feel that the later is more loosely coupled and encapsulated than DAO. I would therefore strongly recommend giving that a look.

> Let's use a simple example of a Person who has

> Addresses. And let's say your code needs to retrieve

> a person, and then later, lazily, needs to retrieve

> this person's addresses. How does DAO suggest you do

> this?

>

Now as mentioned above DAO would not suggest anything but more commonly there are three patterns utilized for lazy loading."lazy initialization", "virtual proxy", and "value holder" what you want to use is a choice made based on the prevailing conditions. However it should be kept in mind that while there definitely are some advantages of lazy load, there are some cons as well, particularly to many database calls which is an expensive process and thats where identity map pattern jumps in.

> The first part, retrieving a Person is

> straightforward. You retrieve a PostgresPersonDAO

> (for example), and call the method "getPerson()"

> passing it along any query information necessary. It

> returns a plain 'ol Person object (transfer object),

> with all the attributes of that person.

>

> The second part, however, confuses me. I have a

> person object. It seems like the most basic

> relational thing I'd want to do now is call

> myPerson.getAddresses() to return a list of

> addresses. In order to implement this method however,

> now my DAO code needs to be sprinkled into my simple

> Person object. Is that right? Does that break the

> pattern? Can the transfer object also act as a DAO

> client?

>

Now again that depends, in Martin Fowler's terms it would be a function od if there is a distinct boundary between the two. For the domain model are you using table module, or Domain Object Model. In case of second a distinction is required between the gateway object (DAO) in this case and the mapper object.

> if this is the case, your DAO will have "instance

> methods", meaning they ACT ON an instance of Person,

> but these methods must take in a Person, since DAOs

> carry no state:

>

> > public List getAddresses(Person),

> public void save(Person)

>

>

> However, they also carry more "static" style getter

> methods, meaning they return an instance of Person,

> but do not require an instance of Person:

>

> > public Person getPersonByPhoneNumber(String num);

> public Person getPersonByName(String name);

>

>

> Perhaps I am just confirming my understanding of this

> pattern and that really there is no distinction here.

> But also however, it often makes me think that Person

> should extend from a DAO that have access to Person's

> internals (that sounds bad), so that the

> "instance"-style methods, are really, in actuality,

> instance methods.

>

That relationship makes no sense to me, IMHO. refer to LSP

> DAO experts, or interested reads, any thoughts on

> this would be much appreciated.

kilyasa at 2007-7-13 15:47:47 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

Thanks for your responses. I realize now that a look at some of Martin Fowler's patterns, and a more detailed understanding of them, would have aided in this discussion - because what I'm driving at I think gets at the heart of some of his Data Source Architectural Patterns. I'd like to reformulate what I was saying, more clearly I hope, in this framework.

The patterns I talk about are here under Data Source Architectual Patterns:

http://www.martinfowler.com/eaaCatalog/index.html

DAO pattern is not an "instance to record" correlation pattern. Martin Fowler's Active Record and Row Data Gateway are "instance to record" patterns, meaning that there's an object that mirrors a datastore record. (this is what I was getting at in my awkwardly phrased "instance-style" discussion) I was initially confused because I was under the impression that transfer objects in DAO were supposed to be representative of a record. But this, afaik, is not the case. Transfer objects are allowed to differ substantially from what a record in your datastore looks like. This is (one of) its supposed advantages.

I guess my concern was that DAO was starting to look a little bit like Fowler's Table Data Gateway - a pattern which seems like a pretty brute force (or should i say simple) way of separating data access out from a domain object. It just shoves any and all data access methods in that gateway, so that the gateway just starts to grow out of control with all these methods (finder methods, saves, and deletes, etc). The Row Data Gateway seems "cleaner" at least.

But perhaps that last paragraph misses the point. The point is, if you need to allow your domain model to differ substantially from your data model, DAO, Data Mapper, (and Table Data Gatway?) are the way to go.

However, if we're just talking about abstracting data access, and things map pretty well 1 to 1 no matter if we're talking postgres, mysql, XML, perhaps I should be looking at another pattern, where I can take advantage of the simpler APIs suggested by ActiveRecord or even the Row Data Gateway.

Hopefully this makes more sense. Thanks for your thoughts.

nootcha at 2007-7-13 15:47:47 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> Thanks for your responses. I realize now that a look

> at some of Martin Fowler's patterns, and a more

> detailed understanding of them, would have aided in

> this discussion - because what I'm driving at I think

> gets at the heart of some of his Data Source

> Architectural Patterns. I'd like to reformulate what

> I was saying, more clearly I hope, in this

> framework.

>

> The patterns I talk about are here under Data Source

> Architectual Patterns:

>

> http://www.martinfowler.com/eaaCatalog/index.html

>

> DAO pattern is not an "instance to record"

> correlation pattern. Martin Fowler's Active Record

> and Row Data Gateway are "instance to record"

While Active Record does not exactly fall into the data access category, there is "Table Data Gateway" as well which is not an "instance of Record".

> patterns, meaning that there's an object that mirrors

> a datastore record. (this is what I was getting at in

> my awkwardly phrased "instance-style" discussion) I

> was initially confused because I was under the

> impression that transfer objects in DAO were supposed

> to be representative of a record. But this, afaik, is

> not the case. Transfer objects are allowed to differ

> substantially from what a record in your datastore

> looks like. This is (one of) its supposed

> advantages.

>

> I guess my concern was that DAO was starting to look

> a little bit like Fowler's Table Data Gateway - a

> pattern which seems like a pretty brute force (or

You are right.

> should i say simple) way of separating data access

> out from a domain object. It just shoves any and all

> data access methods in that gateway, so that the

> gateway just starts to grow out of control with all

> these methods (finder methods, saves, and deletes,

Well Table Data Gate way is not actually designed for the "Domain Model" It would come with the "Table Module" in which scenario it would fit perfectly. Now in order to understand this you would have to develop an understandingg of the differences between "table module and Domain Model".

> etc). The Row Data Gateway seems "cleaner" at least.

>

Well it sure is, but then there is "data mapper" which is even cleaner, so there is no final yes/no on which pattern is the best, it is based on the requirements and considerations for a particular application.

> But perhaps that last paragraph misses the point. The

> point is, if you need to allow your domain model to

> differ substantially from your data model, DAO, Data

> Mapper, (and Table Data Gatway?) are the way to go.

>

Now I would differ from that. The idea is not to differ Domain Model from Data Access layer but it is to decouple it. The degree of decoupling varies. You might want to use "Active Row" in which case there would be little or no decoupling while you might decide to go with "Domain Model" and "Data Mapper".

> However, if we're just talking about abstracting data

> access, and things map pretty well 1 to 1 no matter

> if we're talking postgres, mysql, XML, perhaps I

> should be looking at another pattern, where I can

> take advantage of the simpler APIs suggested by

> ActiveRecord or even the Row Data Gateway.

>

In that case I would ask is your business logic simple enough and data straight forward to go that way, for else the maintainability time graph is going to rise exponentially.

> Hopefully this makes more sense. Thanks for your

> thoughts.

HTH

kilyasa at 2007-7-13 15:47:47 > top of Java-index,Other Topics,Patterns & OO Design...
# 5

> Well Table Data Gate way is not actually designed for

> the "Domain Model" It would come with the "Table

> Module" in which scenario it would fit perfectly.

> Now in order to understand this you would have to

> o develop an understandingg of the differences

> between "table module and Domain Model".

Well, I ordered the martin fowler book. :) But it hasn't arrived yet. So, no I don't entirely understand the difference, except table module I guess maps more directly to your schema, where as domain model maps more directly to your .. err .domain?

> Well it sure is, but then there is "data mapper"

> which is even cleaner, so there is no final yes/no on

> which pattern is the best, it is based on the

> requirements and considerations for a particular

> application.

But doesn't the data mapper pattern, like DAO, put finder methods alongside "instance for record" methods? Of course, this is an arbitrary definition of "clean".

> Now I would differ from that. The idea is not to

> differ Domain Model from Data Access layer but it is

> to decouple it. The degree of decoupling varies.

> You might want to use "Active Row" in which case

> e there would be little or no decoupling while you

> might decide to go with "Domain Model" and "Data

> Mapper".

> In that case I would ask is your business logic

> simple enough and data straight forward to go that

> way, for else the maintainability time graph is going

> to rise exponentially.

Basically, I need to familiarize myself with some of these concepts, but my main goal is to decouple the data access from the business objects. Beyond that, I guess, is gravy. The system uses a legacy XML file system, which I'd one day like to replace with an RDMS. So I'm looking for a good design that will allow this transition to be smooth. But understanding that there are several options is of course liberating and, at times, confusing.

Anyhow thanks for your input/clarification.

nootcha at 2007-7-13 15:47:47 > top of Java-index,Other Topics,Patterns & OO Design...