Dao + connection

Olá…
Estou tentando utilizar alguns DAOs, até aí tudo bem.
Mas cheguei no ponto de criar a conexão com o DB…
Estou pensando em utilizar um pool de conexões também!

Qual seria a melhor forma de criar essa conexão ? ter um método que “fale” com o DataSource e me retorne a conexão ?

Obrigado!

Seria bom que o seu Dao tivesse acesso ao pool e pedisse a ele a conexão.

Ou…usando injecao de dependencia.
Alguem pegaria a conexao do teu pool e “injetaria” no teu Dao.
Eu ainda prefiro essa abordagem.

]['s

Também acho injeção de dependência uma abordagem muito melhor do que cada DAO pedir uma conexão pro pool.

Em um cenário em que um DAO chama outro, é mais conveniente injetar a conexão atual pro DAO chamado do que fazer com que esse também peça uma conexão.

Se no caso ainda houver transação, aí fedeu de vez… Não vejo outro modo de fazer DAOs com transação sem usar DI pra passar as conexões.

Olá!

Em uma app de final de curso, no contrutor do meu dao eu faço assim:


public EmpresaDAO() {
   
    conn = SabesDataSource.getConnection();    

}

Quando eu chamo este método getConnection da classe SabesDataSource, se a conexão não está aberta e a transação não foi iniciada, ele cria pra mim e inicia a transação.

Eu acho esta abordagem bém legal. Vc poderia fazer com que este método getConnection soubesse pegar sua connexão à partir de um pool.

Vc pode depois cria um GenericAbstractDAO por exemplo com um contrutor igual ao que citei acima. Ai todos seus DAO’s estendem ele e herdam esta forma de coletar a connection!

Abraços!
Thiago Senna

Thiago,

Nesse teu exemplo que controla o ciclo de vida da transacao? Quem faz o commit ou rollback? E ainda, se tens operacao em cascata como fica as transacoes?

]['s

Olá Fabio!

Eu tenho também os métodos

SabesDataSource.commit();
SabesDataSource.rollback();

A idéia inicial é controlar a transação em minhas actions!

Alguma crítica? Quer que eu poste o código do SabesDataSource?

Abraços!
Thiago

Thiago, você poderia postar o código como exemplo ?

Muito Obrigado!

[code]
package br.umc.sabes.integracao.util;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

import org.apache.log4j.Logger;

public class SabesDataSource {

private static final ThreadLocal threadConnection = new ThreadLocal();

private static final SabesDataSourceHelper sabesDataSourceHelper =  new SabesDataSourceHelper();

private static final String connectionText = 
	sabesDataSourceHelper.getProperty("dbMySQLDriver") + "://" +
	sabesDataSourceHelper.getProperty("dbHost") + "/" + 
	sabesDataSourceHelper.getProperty("dbName") + "?" + 
	"user=" + sabesDataSourceHelper.getProperty("dbUserName") + "&" +
	"password=" + sabesDataSourceHelper.getProperty("dbUserPassword");

private static final Logger logger = Logger.getLogger(SabesDataSource.class);

public static Connection getConnection() {
	
	Connection c = (Connection) threadConnection.get();		
	
	try {
		if ( c == null) { 
			logger.debug("Criando uma nova conexão");
			Class.forName("com.mysql.jdbc.Driver").newInstance();
			c = DriverManager.getConnection(connectionText);
			c.setAutoCommit(false);
			threadConnection.set(c);
		}
	} catch (Exception ie) {
		logger.debug(ie.getMessage(), ie);
		ie.printStackTrace();
	} 
	
	return c;
}

public static void closeConnection() {
	
	logger.debug("Fechando conexão!");
	
	Connection c = (Connection) threadConnection.get();
	threadConnection.set(null);
	
	try {
		if ((c != null) && (!c.isClosed())){
			c.close();
		}
	} catch (SQLException sqle) {
		logger.debug(sqle.getMessage(), sqle);
		sqle.printStackTrace();
	}		
}

public static void commitTransaction() {
	
	logger.debug("Commitando transação!");
	
	Connection c = (Connection) threadConnection.get();		
	
	try {
		if (( c != null) && (!c.isClosed())) {
			c.commit();				
		}
	} catch (SQLException sqle){
		rollbackTransaction();			
	}		
}

public static void rollbackTransaction() {
	
	logger.debug("Executando RollBack na transação!");
	
	Connection c = (Connection) threadConnection.get();		
	
	try {
		if (( c != null) && (!c.isClosed())) {
			c.rollback();				
		}
	} catch (SQLException sqle){
		logger.debug(sqle.getMessage(), sqle);
		sqle.printStackTrace();			
	} finally {
		closeConnection();
	}		
}

}[/code]

Tá ai… Façam críticas à vontade!

Abraços!
Thiago

Fazer commit, rollback de transações dentro do Action é muito feio, o código de acesso ao banco de dados não pode se “espalhar” para fora da camada de persistência (ou pelo menos não deveria poder).

Se isso é uma aplicação web, você poderia usar um filtro pra fazer isso, dar o commit ou rollback da transação e fechar a conexão quando tudo terminasse, mas não deixe esse código dentro do action.

Boa! Acho que colocar o controle da transação em um filtro é mais conveniente!

Se for assim, os meu DAO’s devem garantir o Rollback? Correto?

[quote=Thiago Senna]
Se for assim, os meu DAO’s devem garantir o Rollback? Correto?[/quote]

O filtro pode fazer isso também, vai evitar muitas linhas de código repetidas nos seus DAOs.

[quote=Maurício Linhares][quote=Thiago Senna]
Se for assim, os meu DAO’s devem garantir o Rollback? Correto?[/quote]

O filtro pode fazer isso também, vai evitar muitas linhas de código repetidas nos seus DAOs.[/quote]

Blz! Deixa comigo entaum!

Abraços!
Thiago

A meu ver o Dao tem que ficar independente da camada de transacao, justamente pra nao ficar acoplado.
Imagina que hoje tu tem um modelo de transacao baseado so no JDBC, utilizando o commit e rollback da interface connection e derrepente tu resolve mudar isso utilizando JTA por exemplo. Se isso estiver acoplado no teu DAO o refactoring vai ser grande.

Esse esquema de filtro é bom, antes de usar o Spring com AOP eu fazia parecido com isso, mas usando um interceptor do WebWork.

]['s

Hm, eu ficaria também com a abordagem da inversão de controle neste caso, para os mais moderninhos, a Injeção por Dependência :mrgreen:
O Spring tem uma abordagem muito legal, e a configuração do teu JDBC não precisa ficar dentro de uma “Connection”, deixa que tudo isso seja feito pelo spring :wink:

Uma tradução do artigo do Fowler feita pelo Ronald Tetsuo :wink:
http://www.javafree.org/content/view.jf?idContent=1

Abraços!

Isso depende da forma como seus DAOs são construidos.

Se você estiver usando uma abstract factory para criar os DAOs, deixa com a factory a responsabilidade de arrumar a connection e passar para cada DAO.

Se não estiver usando factories, o mais facil é usar uma thread local com a connection, isso vai diminuir o acoplamento inferente (esse é o termo?) aos DAOs.

Você ainda pode usar um container de IoC, que vai fazer a injeção das dependências dos teus DAOs, a connection.