Using Same Connection for 2 DAOs

I want to use 2+ DAOs in a transaction. I don't have a transaction manager, so I would like to only use one connection object to execute the transaction. How do I pass the connection object? Where do I create the connection? Where is the transaction started/ended?

Solution 1:

Use a business object, create the connection and pass it to the DAOs in constructor:

Connection con = ...

con.setAutoCommit(false);

Num1DAO dao1 =new Num1DAO(con);

dao1.updateX(...);

Num2DAO dao2 =new Num1DAO(con);

dao2.updateY(...);

con.commit();

Solution 2:

Use a business object, create the connection and pass it to the DAOs in the method:

Connection con = ...

con.setAutoCommit(false);

Num1DAO dao1 = DAOFactory.getDAO1();

dao1.updateX(con, ...);

Num2DAO dao2 = DAOFactory.getDAO2();

dao2.updateY(con, ...);

con.commit();

Solution 3:

One DAO calls the other DAO with the connection:

class Num1DAO{

publicvoid updateX(...){

Connection con = ...

con.setAutoCommit(false);

Num2DAO dao2 = DAOFactory.getDAO2();

dao2.updateY(con, ...);

con.commit();

}

}

I currently use solution 3, but don't like it. How can I get 2+ DAOs share the same connection? Am I missing something? All DAOs are in the same database.

[1749 byte] By [mhhdudua] at [2007-11-26 14:17:05]
«« xml dom
»» emergency
# 1

> I want to use 2+ DAOs in a transaction. I don't have

> a transaction manager, so I would like to only use

> one connection object to execute the transaction. How

> do I pass the connection object? Where do I create

> the connection? Where is the transaction

> started/ended?

>

> Solution 1:

> Use a business object, create the connection and pass

> it to the DAOs in constructor:

> >Connection con = ...

> con.setAutoCommit(false);

>Num1DAO dao1 = new Num1DAO(con);

> dao1.updateX(...);

>Num2DAO dao2 = new Num1DAO(con);

> dao2.updateY(...);

>con.commit();

> ode]

This is an example of constructor injection. This will work fine.

> Solution 2:

> Use a business object, create the connection and pass

> it to the DAOs in the method:

> [code]

>Connection con = ...

> con.setAutoCommit(false);

>Num1DAO dao1 = DAOFactory.getDAO1();

> dao1.updateX(con, ...);

>Num2DAO dao2 = DAOFactory.getDAO2();

> dao2.updateY(con, ...);

>con.commit();

> ode]

This will work, too. The only drawback is that it makes a relational database explicit in your API. What if you weren't talking to a relational database? What if an LDAP or an XML stream was the backing store? Now the DAO's interface has to change, because those other repositories don't use java.sql.Connection.

> Solution 3:

> One DAO calls the other DAO with the connection:

> [code]

> class Num1DAO {

>public void updateX(...) {

>Connection con = ...

>con.setAutoCommit(false);

>Num2DAO dao2 = DAOFactory.getDAO2();

>dao2.updateY(con, ...);

>con.commit();

> }

> }

>

>

> I currently use solution 3, but don't like it.

Why not? If the only way you access the client classes is through the parent, I think that's fine. If you were doing ORM, you might only have DAOs for the parent classes.

> How

> can I get 2+ DAOs share the same connection? Am I

> missing something? All DAOs are in the same database.

I'd vote for a combination of (1) and (3) if you don't ever access the children except through the parent. If that's not true, go with (1).

%

duffymoa at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 2
My response got a bit messed with your code tags. Sorry, I should have previewed it.I'd also recommend that you start with an interface.%
duffymoa at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 3

Thanks for the response. The problem is, the DAO is fixed to database connections. What If I want to create a FileDAO later on?

The Interface

interface FooDAO {

public void update(Connection con, Object value);

}

The DB DAO (OK)

public class DBFooDAO implements FooDAO {

public void update(Connection con, Object value) {

...

}

}

The File DAO (cannot use java.sql.Connection)

public class FileFooDAO implements FooDAO {

public void update(Connection con, Object value) {

//... huh! con is for databases but NOT for files

}

}

How can I make the DAO independent of java.sql.Connection?

mhhdudua at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> Thanks for the response. The problem is, the DAO is

> fixed to database connections. What If I want to

> create a FileDAO later on?

>

> The Interface

> > interface FooDAO {

>public void update(Connection con, Object value);

>

>

> The DB DAO (OK)

> > public class DBFooDAO implements FooDAO {

> public void update(Connection con, Object value)

> {

>...

> }

>

>

> The File DAO (cannot use java.sql.Connection)

> > public class FileFooDAO implements FooDAO {

> public void update(Connection con, Object value)

> {

> //... huh! con is for databases but NOT for

> files

>}

>

>

>

> How can I make the DAO independent of

> java.sql.Connection?

That's why I said that I didn't like this option. I'd prefer constructor injection. I'd write a FooDao like this:

public interface FooDao

{

Foo findById(Long id);

List<Foo> findAll();

void save(Foo f);

void update(Foo f);

void delete(Foo f)

void delete(Long id);

}

public class FooJdbcDao implements FooDao

{

private Connection connection;

public FooJdbcDao(Connection c)

{

this.connection = c;

}

// Jdbc implementation for all FooDao methods here.

}

%

duffymoa at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 5
I still don't quite like it. How does a DAO1 access a DAO2. 1) Do they use a DAOFactory? 2) Or does DAO1 directly instantiate DAO2?
mhhdudua at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 6

> I still don't quite like it. How does a DAO1 access a DAO2.

It's a private data member of the first DAO if you must do it that way.

> 1) Do they use a DAOFactory?

That can work. What's the factory doing for you? Just instantiate it.

> 2) Or does DAO1 directly instantiate DAO2?

It can do that.

Why are you so hung up on how the first DAO instantiates the second?

If I were doing this with Spring, I'd have one DAO and I'd use its JDBC template.

%

duffymoa at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 7
I guess I might be too uptight about it?
mhhdudua at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 8

Setter injection or constructor injection are the way to go.

The Spring Framework defines a generic DaoSupport class that is extended by specific DAO support classes. Your DAO's then extend these specific DAO support classes and use setter injection (or constructor injection) to set any required properties. After this has been done you can retrieve a "Template" helper class that simplifies data access.

http://www.springframework.org/docs/api/org/springframework/dao/support/DaoSupport.html

YoGeea at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 9

Personally I think its just fine. If you want to create a FileDAO, well that is a different DAO. Cross that bridge when you get to it. At that time it will be easier and clearer to see how to abstract the non-common parts out.

For me, I simply put a layer on top of my 'DAO' and started calling that layer the DAO and my DAO something else...

_dnoyeBa at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...
# 10

Try javax.transaction.UserTransaction

as follows:

public class SomeBO{

public void updateSomeData(){

InitialContext ctx = new InitialContext();

UserTransaction ut = (UserTransaction)

ctx.lookup("java:comp/UserTransaction");

ut.begin();

Num1DAO dao1 = new Num1DAO();

dao1.updateX(...);

Num2DAO dao2 = new Num2DAO();

dao2.updateY(...);

ut.commit();

//try catch not shown for simplicity

// ut.rollback() if any errors

}

}

where each dao can work independent of the other.

nsenthila at 2007-7-8 2:07:24 > top of Java-index,Other Topics,Patterns & OO Design...