Galera, estou com uma dúvida cruel.
Criei essa classe para me fornecer uma funcinalidade muito util: Conexões ao Banco de Dados.
Pensei em fazer essa classe pq toda hora criamos aplicações q conectam ao BD. Assim diminuo meu trabalho!
O Problema é q não sei se estou fazendo de maneira correta.
O q vcs acham dessa forma q estou utilizando?
Como vcs costumam fazer?
[code] public abstract class UtilBDConnection {
/**
* Pegar conexões por DataSource
*/
public static Connection getConnectionByDataSource( String myDS ) throws Exception {
Context context = new InitialContext();
DataSource dataSource = (DataSource)context.lookup( myDS );
return dataSource.getConnection();
}
/**
* Pegar conexões por parâmetros
*/
public static Connection getConnectionByParameters( String url, String user, String password, String DRIVER ) throws Exception {
Class driverClass = Class.forName( DRIVER );
return DriverManager.getConnection( url, user, password );
}
/**
* Fechar conexão
*/
public static void closeConnection( Connection connection, Statement statement, ResultSet resultSet ) throws Exception {
if( resultSet != null ) {
resultSet.close();
resultSet = null;
}
if( statement != null ) {
statement.close();
statement = null;
}
if( connection != null ) {
connection.close();
connection = null;
}
}
}[/code]
Um exemplo de sua utilização:
[code] public List list() throws Exception {
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
List list = new ArrayList();
try {
connection = UtilBDConnection.getConnectionByDataSource( "java:comp/env/jdbc/CMMySQL" );
statement = connection.createStatement();
resultSet = statement.executeQuery( "SELECT * FROM test" );
while( resultSet.next() ) {
list.add( resultSet.getString(1) );
}
} finally {
UtilBDConnection.closeConnection( connection, statement, resultSet );
}
return list;
}[/code]
Valeu!
- Voce nao esta usando um connection pool
- Voce nao esta fechando os result sets e statements
- Voce esta duplicando varias linhas de codigo ao pegar a conexao, tratar o erro e fechar a conexao em cada metod.
Dica: utilize um template method
Rafael
Rafael, estou utilizando o pool do Tomcat. Configuro ele no context da aplicação. Mas o q vc quiz dizer é q seria melhor trabalhar com um pool independente do container, tipo DBCP ou C3PO?
A respeito de fechar as conexões, eu passo, além do objeto connection, o statement e o resultSet para o método UtilBDConnection.closeConnection( connection, statement, resultSet ). Nesse método ele fecha tudo.
Na questão dos tratamentos de erros, realmente, preciso tratá-los direto no método.
Valeu pela dica do Template Method!
Ok, mas e se vc precisa se mais statements e resultsets? vai ficar meio estranho fechar um pouco num canto e o resto em outra parte…
Rafael
Rafael, qd vc quiz dizer: “duplicando linhas de código”, é pq toda hora eu preciso chamar o método UtilBDConnection.getConnectionByDataSource( “java:comp/env/jdbc/CMMySQL” ) para conseguir uma conexão?
E o mesmo acontece com UtilBDConnection.closeConnection( connection, statement, resultSet ) ao fechar conexão?
Isso não tem nada a ver com o fato de eu estar trabalhando com métodos static, certo?
Já com TemplateMethod eu usaria um “esqueleto” de uma classe abstrata na qual eu teria um método getConnection() e closeConnection() que fariam esse papel pra mim?
E se eu implementasse esses métodos com uma chamada a minha classe? Assim:
[code] public abstract class TemplateMethod() {
public abstract void getConnection();
public abstract void closeConnection();
public abstract List list();
public final List execute() {
getConnection(); //Abre a conexão
List list = list(); //Faz a pesquisa
closeConnection(); //Fecha a conexão
return list; //Retorna o resultado
}
}
public class ConcreteClass() extends TemplateMethod {
private final String myDS = “java:comp/env/jdbc/CMMySQL”;
private Connection connection = null;
private Statement statement = null;
private ResultSet resultSet = null;
//Implementei utilizando minha classe UtilBDConnection
public void getConnection() {
connection = UtilBDConnection.getConnectionByDataSource( myDS );
}
public List list() {
////Faço minha consulta
}
//Implementei utilizando minha classe UtilBDConnection
public void closeConnection() {
UtilBDConnection.closeConnection( connection, statement, resultSet );
}
}[/code]
Eu poderia até criar um outro método para fechar minhas conexões, mantendo minha conexão aberta e fechando somente o statement e o resultSet, para poder reutilizar a mesma connection.
???
Quase. Pegar a conexao e tratar erros sao coisas do template. As classes filhas somente fazem o execute. Ficaria assim:
public abstract class TemplateMethod() {
private Connection connection;
public TemplateMethod() {
this.connection = this.openConnection();
}
private Connection openConnection() {
// abre a conexao com o banco
}
protected Connection getConnection() {
return this.connection;
}
private void closeConnection() {
// fecha / libera a conexao
}
public abstract Object doAction() throws Exception;
public final Object execute() {
try {
return this.doAction();
}
catch (Exception e) {
throw new AlgumaRuntimeExceptionTua(e);
}
finally {
this.closeConnection();
}
}
}
e entao, para usar, vc faz algo como
TemplateMethod t = new TemplateMethod() {
public Object doAction() throws Exception {
Statement s = this.getConnection();
// Trabalha com o banco
return algumaCoisa;
}
}.execute();
Veja que pegar a Exception no execute() e relancar uma RuntimeExeption eh para te livrar da necessidade de fazer try-catch nos lugares onde vc for usar o pattern.
Como voce ver, o seu codigo fica muito mais limpo, focando-se apenas na parte importante da tarefa.
Rafael