To DAO or not to DAO
Hi all,
A small part of my long-lived application loads a bunch of data into a business object from a database. The data is placed in the source database by a different application - we'll ignore that for now.
When I wrote this business object I was unaware of DAOs and dependency injection and a lot of the other sexy stuff. Subsequently the (lightweight) business object has load() and save() methods that contain JDBC.
A recent change has meant I now have an *additional*, different source of data - which happens to be CSV files. I need to be able to read from either.
Option 1
I feel that the load() and save() should be split out into DAO - then I could create a different DAO for the CSV file version. However, the business object itself adds very little to the data - it's pretty much a DAO in itself.
I guess my question here is when a business object is so tightly bound to a data set, is the use of a DAO overkill? #
Option 2
Take the business object as-is, make it an abstract base class with abstract load() and save() methods then have one subclass for the database one and one subclass for the CSV one.
Option 3
Pre-process the CSV file and insert it into the database in the expected format (keep the business object the same).
Many thanks for any thoughts,
Chris
[1381 byte] By [
ClothEarsa] at [2007-10-3 3:47:28]

Throw away the last 2 options.
I think a nice solution can be having an interface "Service", an abstract class "AbstractService" that implements the "Service" interface.
"PersistenceService" can extend "AbstractService".
"DBPersistence" can extend "PersistenceService".
"DBPersistence" would have methods for returning DAOs.
"FilePersistence" can extend "PersistenceService".
"Service" can expose a method "openService".
In case of "DBPersistence" you would do db configuration stuff inside the " open method "
In "FilePersistence" you would open and prepare the file inside the " open method "
You can add methods like " closeService " to the "Service interface" and other stuff like registering listeners and so on.
"DBPersistence" would have methods for returning each type of DAOs.
You can initialize "DBPersistence" within the " openService() " maybe creating a "DBPersistenceFactory" that reads a config file and configures your "DBPersistence" and set them DAOs ( for hibernate or whatever ).
Regards.
Thanks for this. I think see what you mean - there's a lot in there!
In the end I have implemented it as a database DAO and a file DAO which both return the business object in question. I also moved some stuff around from a class that was a caled MyBusinessObjectCache.java to one called MyBusinessObjectService.java which has a
setMyDAO( MyDAO myDAO )
and a
getMyBusinessObject( ... params ...)
It still does some caching but recent work on a Spring course led me to use the DAO/Service object solution.
Thanks again for your suggestion.
> Hi all,
>
>
> A small part of my long-lived application loads a
> bunch of data into a business object from a database.
> The data is placed in the source database by a
> different application - we'll ignore that for now.
>
> When I wrote this business object I was unaware of
> DAOs and dependency injection and a lot of the other
> sexy stuff. Subsequently the (lightweight) business
> object has load() and save() methods that contain
> JDBC.
>
> A recent change has meant I now have an *additional*,
> different source of data - which happens to be CSV
> files. I need to be able to read from either.
>
>
>
> Option 1
>
> I feel that the load() and save() should be split out
> into DAO - then I could create a different DAO for
> the CSV file version. However, the business object
> itself adds very little to the data - it's pretty
> much a DAO in itself.
>
> I guess my question here is when a business object is
> so tightly bound to a data set, is the use of a DAO
> overkill? #
Yes. if u are keeping the same way you have mentioned, then you have to write separate program to load and save() for the source "CSV " files. It makes you to put some more code for the program which is using yourlong-lived application . i mean you might have to change the code for modules which depends the your long lived application.
>
>
> Option 2
>
> Take the business object as-is, make it an abstract
> base class with abstract load() and save() methods
> then have one subclass for the database one and one
> subclass for the CSV one.
>
It will be fine.just follow the code given by previous post.
thanks,
nvseenu
> Option 3
>
> Pre-process the CSV file and insert it into the
> database in the expected format (keep the business
> object the same).
>
> Many thanks for any thoughts,
> Chris
Hi,
I don't know if anyone is still listening to this thread but, in the interests of learning something myself and for anyone else, I'd like to dissect the earlier reply I got and compare it with the solution I've implemented. Please do scream if I've done something evil - my version *seems* to be okay.
For completeness I repeat an earlier point that I wrote the initial code before I came to learn about DAOs and service objects. I've also just attended a Spring course so am keen on the whole "injection" thing now (then I can put the resulting code into the Spring env).
Right - here we go...
I think a nice solution can be having an interface "Service",
Check- I've created one of those. It contains a set DAO method and one or more getMyBunsinessObject( ... ) method ...
an abstract class "AbstractService" that implements the "Service" interface.
... I've not done this. I simply created a service implementation ...
"PersistenceService" can extend "AbstractService".
... I guess I've gone straight to "PersistenceService" ...
"DBPersistence" can extend "PersistenceService".
"DBPersistence" would have methods for returning DAOs.
"FilePersistence" can extend "PersistenceService".
... this is where I get confused. I'm getting confused with the responsibilities of the Service and DAO.
My understand (and I could be wrong) is that a "Service" object is something that I can ask for something. In my case I call the
public MyBusinessObject getMyBusinessObject( .. )
Where I have the separation of DB/CSV file knowledge is outside of the Service. That functionality is in the DBDAO or CSVDAO DAO implementations.
I "inject" the type of DAO I want to use into the Service using
public void setDAO( MyBusinessObjectDAO businessObjectDAO )
"Service" can expose a method "openService".
In case of "DBPersistence" you would do db configuration stuff inside the " open method "
In "FilePersistence" you would open and prepare the file inside the " open method "
By this point I think I'm on a different road (and not necessarily the right one)... I have all the connection/file open
stuff in the DAO implementations.
You can add methods like " closeService " to the "Service interface" and other stuff like registering listeners and so on.
I get the idea of adding open/close/listener functions to the service. I guess the more service objects I write the more this will become apparent.
"DBPersistence" would have methods for returning each type of DAOs.
I'm struggling now. I set the DAO into my service rather than the service passing them back to me.
You can initialize "DBPersistence" within the " openService() " maybe creating a "DBPersistenceFactory" that reads a config file and configures your "DBPersistence" and set them DAOs ( for hibernate or whatever ).
By this point - although I understand what you're describing - I can't relate it to my solution.
My questions on this are
1) Do I have a proper understanding of the responsibility of a "Service" object? Yours creates/returns DAOs - mine has one injected in order to function. Anyone got any good info on this?
2) Your solution, correct me if I'm wrong, builds the separation of DB or CSV flavours into the Service object.
3) I'm not clear what the Factory object suggested at the end would create. Services? DAO?
Hi,
3) I'm not clear what the Factory object suggested at the end would create. Services? DAO?
HereNothing to confuse .Basically your service is a DAO service. I mean your logic is going to load and store the business objects from/to source such as DB or CSV.
To avoid the confusion , you could rename your "Service" interface as "ServiceDAO"
So Factory always returns appropriate ServiceDAO such as DBServiceDAO or CSVServiceDAO based on configuration file passed.
1) Do I have a proper understanding of the responsibility of a "Service" object? Yours creates/returns DAOs - mine has one injected in order to function. Anyone got any good info on this?
" Service " is the interface which provides set of services like getBusinessObject(), setBusinessObject().
It has the responsiblity itself whether methods should be implemented by using Db or CSV as a source or not .
Once you finished this "Service" implementation, Other programs do not have to know about your implementation whether job have been done through DB or CSV, except passing the configuration file.
They simply pass the configuration file to your factory which can select appropriate Service implementation based on information in configuration file .
Acording to myself, injection method
" public void setDAO( MyBusinessObjectDAO businessObjectDAO )"can be avoided.
Here you need to construct the factory instructed by jfreebsd .
class Factory // Make this class as Singleton.
{
public static ServiceDAO getServiceDAO(File config)
{
ServiceDAOdao=null;
// read the configuration file
if( DB info is in Config file)
{
dao = new DBServiceDAO( Pass the configuration );
}
else if( CSV info in Config file )
{
dao = CSVServiceDAO( Pass the configuration );
}
return dao;
}
}
So you can get appropriate ServiceDAO from the factory by passing configuration file
and start to use it.
Hope it will clear you,
nvseenu
Ah - I see. It was applying preconceived notions of Service and DAO to your solution that confused me.
I think we're talking about the same thing only viewed from different angles.
Your solution has an DAO service that decides internally what flavour of DAO to return, I assume you then use the returned DAO to retrieve your BusinessObject.
In my version the "Service" object is what is used to retrieve the BusinessObject. Internally this Service uses an DAO to retrieve the BusinessObject and it passes that back. The DAO is injected into the Service from the outside - the approach popular in Spring and other IoC containers. The burden of which flavour of DAO to inject is on whatever sets up the Service. The advantage for me in using this approach is that the Service oject can cache BusinessObjects since it sits between the calling application and the underlying DAO.
In an attempt to clarify things, here are my three interfaces...
=============================================
IMyBusinessObject
=============================================
package uk.co.horizon_asset.yieldcurve.domain;
import java.util.*;
import uk.co.horizon_asset.yieldcurve.domain.HAL_MyBusinessObject.*;
public interface IMyBusinessObject {
... methods ..
}
=============================================
IMyBusinessObjectDAO
=============================================
package uk.co.horizon_asset.yieldcurve.dao;
import uk.co.horizon_asset.yieldcurve.*;
import uk.co.horizon_asset.yieldcurve.domain.*;
public interface IMyBusinessObjectDAO {
public IMyBusinessObject getMyBusinessObject(String curveCurrency,
java.util.Date closeDate,
String scenarioName) throws Exception;
public void setMyBusinessObject(IMyBusinessObject MyBusinessObject);
}
=============================================
IMyBusinessObjectService
=============================================
package uk.co.horizon_asset.yieldcurve.service;
import java.util.Date;
import uk.co.horizon_asset.yieldcurve.*;
import uk.co.horizon_asset.yieldcurve.domain.IMyBusinessObject;
import uk.co.horizon_asset.yieldcurve.dao.IMyBusinessObjectDAO;
public interface IMyBusinessObjectService {
public IMyBusinessObject getMyBusinessObject(String currency, Date closeDate,
String scenarioName);
public void setMyBusinessObjectDAO(IMyBusinessObjectDAO MyBusinessObjectDAO);
}
> Ah - I see. It was applying preconceived notions of
> Service and DAO to your solution that confused me.
>
> I think we're talking about the same thing only
> viewed from different angles.
>
> Your solution has an DAO service that decides
> internally what flavour of DAO to return, I assume
> you then use the returned DAO to retrieve your
> BusinessObject.
>
>
> In my version the "Service" object is what is used to
> retrieve the BusinessObject. Internally this Service
> uses an DAO to retrieve the BusinessObject and it
> passes that back. The DAO is injected into the
> Service from the outside - the approach popular in
> Spring and other IoC containers. The burden of which
> flavour of DAO to inject is on whatever sets up the
> Service. The advantage for me in using this approach
> is that the Service oject can cache BusinessObjects
> since it sits between the calling application and the
> underlying DAO.
>
> In an attempt to clarify things, here are my three
> interfaces...
>
>
> >
>
> =============================================
> IMyBusinessObject
> =============================================
> package uk.co.horizon_asset.yieldcurve.domain;
>
> import java.util.*;
>
> import
> uk.co.horizon_asset.yieldcurve.domain.HAL_MyBusinessOb
> ject.*;
>
> public interface IMyBusinessObject {
>
> ... methods ..
>
> }
>
>
>
> =============================================
> IMyBusinessObjectDAO
> =============================================
> package uk.co.horizon_asset.yieldcurve.dao;
>
> import uk.co.horizon_asset.yieldcurve.*;
> import uk.co.horizon_asset.yieldcurve.domain.*;
>
> public interface IMyBusinessObjectDAO {
>
> public IMyBusinessObject
> getMyBusinessObject(String curveCurrency,
> java.util.Date
> closeDate,
> String
> scenarioName) throws Exception;
>
> public void setMyBusinessObject(IMyBusinessObject
> MyBusinessObject);
>
> }
>
>
> =============================================
> IMyBusinessObjectService
> =============================================
> package uk.co.horizon_asset.yieldcurve.service;
>
> import java.util.Date;
> import uk.co.horizon_asset.yieldcurve.*;
> import
> uk.co.horizon_asset.yieldcurve.domain.IMyBusinessObjec
> t;
> import
> uk.co.horizon_asset.yieldcurve.dao.IMyBusinessObjectDA
> O;
>
> public interface IMyBusinessObjectService {
>
> public IMyBusinessObject
> getMyBusinessObject(String currency, Date
> closeDate,
> String
> scenarioName);
>
> public void
> setMyBusinessObjectDAO(IMyBusinessObjectDAO
> MyBusinessObjectDAO);
>
>
>
Hi,
I have cleared myself after seeing your interfaces.
According to myself instead of providing the DAO using the method
"setMyBusinessObjectDAO(IMyBusinessObjectDAOMyBusinessObjectDAO); ",
Why don't you pass DAO as an arguement through the constructor of implementation
class of "IMyBusinessObjectService" . ?
Because, to provide the services , DAO is most important. So if you force the user
to set DAO during object instantiation , It will be good .
if you use setDAO() method , user might have a chance to skip.
thanks,
seenu
> According to myself instead of providing the DAO
> using the method
>
> "setMyBusinessObjectDAO(IMyBusinessObjectDAO
>MyBusinessObjectDAO); ",
> Why don't you pass DAO as an arguement through the
> constructor of implementation
>
> class of "IMyBusinessObjectService" . ?
>
> Because, to provide the services , DAO is
> most important. So if you force the user
>
> to set DAO during object instantiation , It will be
> good .
>
> if you use setDAO() method , user might have a
> chance to skip.
I totally agree. I'd just made that edit in fact.
Thanks for your help.
Chris