Pois é, vou acabar usando pela “limpesa” no código; e também pelo fato de que concatenar String´s no Java é um problema de criação de novos objetos desperdíçando memória.
Pois é :), isso é realmente um problema.
Pois é, vou acabar usando pela “limpesa” no código; e também pelo fato de que concatenar String´s no Java é um problema de criação de novos objetos desperdíçando memória.
Pois é :), isso é realmente um problema.
[code]
public abstract class JdbcSupport{
protected Object executarQuery(String query){
Statement statement = null;
ResultSet resultSet = null;
conexao = getConnection();
Object retorno = null
try{
statement = conexao.createStatement();
resultSet = statement.executeQuery(query);
conexao.commit();
retorno = resultSetToModel(resultSet);
}catch(Exception ex){
try { conexao.rollback(); } catch (SQLException e) { e.printStackTrace(); }
}
finally{
liberarConexao(conexao);
liberarStatment(statement);
}
return retorno;
}
public abstract Object resultSetToModel(ResultSet rs);
}
public class JdbcSupportModel extends JdbcSupport{
public Object resultSetToModel(ResultSet rs){
//aqui vc transforma esse resultset no seu objeto de modelo
}
}[/code]
lógico que retornar object é ruim, mas é apenas uma idéia. assim vc não precisa ficar repetindo o código.
Sim concordo que retornar object não é muito legal.
Mas o seu método resultSetToModel pode ser abstrato ou genérico, assim a sub-classe retornaria a lista de entidades no qual ela representa.
Mas essa não é a questão.
Como já tinham falado anteriormente, essa é uma boa idéia, e estou pensando se é possível colocá-la no código.
[quote=ViniGodoy]Quem acha que não tem como fugir dessa estrutura, veja o Spring.
E realmente é pog manter essa estrutura em todo lugar, eu concordo com o xdraculax. Embora ele realmente devesse usar o PreparedStatement, é realmente louvável a preocupação em não repetir código. Repetição de código é uma idiotice, um dos grandes males a serem evitados.[/quote]
Humm… tlv não estejamos falando do mesmo Spring. O que o Spring faz é exactamente o que o mario.fts falou. Esse padrão de tratamento é universal e a razão da sua existência é uma coisa chamada ACID
O codigo fonte está aqui
E o codigo é este:
public Object execute(StatementCallback action) throws DataAccessException {
Assert.notNull(action, "Callback object must not be null");
Connection con = DataSourceUtils.getConnection(getDataSource());
Statement stmt = null;
try {
Connection conToUse = con;
if (this.nativeJdbcExtractor != null &&
this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
}
stmt = conToUse.createStatement();
applyStatementSettings(stmt);
Statement stmtToUse = stmt;
if (this.nativeJdbcExtractor != null) {
stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
}
Object result = action.doInStatement(stmtToUse);
handleWarnings(stmt.getWarnings());
return result;
}
catch (SQLException ex) {
// Release Connection early, to avoid potential connection pool deadlock
// in the case when the exception translator hasn't been initialized yet.
JdbcUtils.closeStatement(stmt);
stmt = null;
DataSourceUtils.releaseConnection(con, getDataSource());
con = null;
throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
}
finally {
JdbcUtils.closeStatement(stmt);
DataSourceUtils.releaseConnection(con, getDataSource());
}
}
O reaproveitamento e a abstração é conseguida pelo uso de classes utilitárias, callbacks e proxys. Tudo com exceções devidamente tratadas.
É tecnologia que permite que em apenas um método e com a estrutura clássica, muita coisas possa ser feita.
Já agora é interessante dar uma olhada no método query.
O ponto não é que não devemos consolidar tudo num método. O ponto é que existem formas certas e formas erradas de consolidar as coisas num método.
Para quem não gosta de pensar em certo e errado: existem formas acopladas e formas desacopladas de consolidar e abstrair.
Então Sérgio. Esse código é exatamente o que o xdraculax estava propondo no início, embora o design dele ainda esteja muito atrás do design do spring, por desconhecimento do JDBC (como vc mesmo citou).
E o método faz exatamente o que você disse para ele não fazer, concentra todo tratamento num lugar só, evitando toda a repetição enfadonha que o JDBC impõe. Talvez você tenha se expressado mal, mas eu entendi que você falou que isso era POG, e que ele deveria reproduzir todo esse código de tratamento várias vezes. E foi isso que deixou o xdraculax de cabelo em pé.
Para um método ainda mais parecido com o que ele fez, veja a implementação do queryForRowSet.
Ok, como contra argumento você vai dizer que o Spring usa as abstrações certas. Entretanto, não dá para negar que o colega estava no caminho certo, e que essa abstração iria surgir cedo ou tarde, a medida que ele necessitasse de recursos mais avançados, como transações. Tanto que, ele mesmo já estava no caminho de copiar as respostas para um novo objeto, como o próprio Spring faz.
[quote=ViniGodoy]Então Sérgio. Esse código é exatamente o que o xdraculax estava propondo no início, embora o design dele ainda esteja muito atrás do design do spring, por desconhecimento do JDBC (como vc mesmo citou).
E o método faz exatamente o que você disse para ele não fazer, concentra todo tratamento num lugar só, evitando toda a repetição enfadonha que o JDBC impõe. Talvez você tenha se expressado mal, mas eu entendi que você falou que isso era POG, e que ele deveria reproduzir todo esse código de tratamento várias vezes. E foi isso que deixou o xdraculax de cabelo em pé.
Para um método ainda mais parecido com o que ele fez, veja a implementação do queryForRowSet.
Ok, como contra argumento você vai dizer que o Spring usa as abstrações certas. Entretanto, não dá para negar que o colega estava no caminho certo, e que essa abstração iria surgir cedo ou tarde, a medida que ele necessitasse de recursos mais avançados, como transações. Tanto que, ele mesmo já estava no caminho de copiar as respostas para um novo objeto, como o próprio Spring faz.[/quote]
O que eu disse foi
“esse método” se refere ao método que foi apresentado. Eu não disse “esse conceito” , nem “essa ideia” , nem "qualquer tipo de método que encapsule o tratamento de statements"
Acho que a diferença é obvia e ha uma mal intrepretação vossa.
A minha objeção principal é colocar o método numa classe abstrata em vez de numa classe especializada. Essa é a principal POG aqui, por achar que colocando em classes abstrata e herdando dela estaria reaproveitando codigo. Não. Reaproveitamento acontece criando classes especificas e chamando-as. Que é o que o Spring faz, o Hibernate e o MiddleHeaven
Repare que o JDBCTemplate é usado por outras classes para executar sql, ele não é herdado.
Tb não referi nada em relação “ao caminho certo” em que ele estaria. Apenas no caminho errado que ele precorreu: o conceito de usar métodos em classes abstratas para reaproveitar codigo.
Colocar o método na classe abstrata e chamá-lo nas especializações é exatamente o que eu faço, não há absolutamente nada de errado nisso. É exatamente o que o Spring faz pelo que estou vendo, e isso não é nenhuma novidade.
Quanto ao tratamento de exceções, não tem nada a ver o que o sergio falou. A questão abordada aqui não era o tratamento de exceções, e sim o problema com o ResultSet.
Sabe aqueles exemplos de livros que querem mostrar a declaração de uma variável e colocam 400 linhas de código para tal? Pois é… não era essa minha intenção; meu foco era o problema de chamada do método e liberação dos recursos IO.
Gostei do códgo do Spring. Lógico, meu código está pobre ainda, comecei a implantar esse conceito agora, por ver o problema de repetição de código, ainda tenho que amadurecê-lo muito.
Infelizmente ainda não consigo desenhar um sistema e codificá-lo de uma vez e nunca ter que melhorar uma linha de código.
Bem, uso classes abstratas para o que elas foram feitas: representar abstrações. Abstrações reutilizáveis entre as implementações, por consequência: reuso de código.
E sim, o sergio disse que reutilizar a mesma estrutura de códgo na classe abstrata era POG (primeira página, msg 14).
[quote=xdraculax]Colocar o método na classe abstrata e chamá-lo nas especializações é exatamente o que eu faço, não há absolutamente nada de errado nisso. É exatamente o que o Spring faz pelo que estou vendo, e isso não é nenhuma novidade.
[/quote]
Não. Veja com mais atenção. O método do spring é publico e a classe não é abstrata nem é feita para ser herdada.
É exactamente esse conceito que estou dizendo que está errado. Vc está equivocadamente associando “abstração” com “classe abstrata”. Não é assim que OO funciona.
Uma “abstração” é a identificação de um conceito ou mecanismo que pode ser tratado como uma unidade em si mesmo. Por exemplo, Cliente é uma abstração. usuário é uma abstração. Contudo, as classes que os representam não são abstratas.
Reuso de codigo não é conseguido via herança. É isso que estou lhe dizendo. Vc usa herança para categorizar (organizar) as ideias, não para reaproveitar codigo.
E sim, o sergio disse que reutilizar a mesma estrutura de códgo na classe abstrata era POG (primeira página, msg 14).[/quote]
A palavra chave ai é “na classe abstrata”. Esse é o problema.
Basicamente vc quer fazer um esquema tipo template method. mas vc não precisa disso e isso não é flexivel. é muito mais simples vc criar uma classe especializada em executar pesquisas JDBC ( como o Spring faz) e depois injetar essa classe nas classes que precisam desse serviço.
É uma questão do design OO e o uso indevido de herança para reaproveitar codigo.
Entendi.
Realmente abstração (AbstractPersistence) não é usada em nenhum lugar realmente como uma abstração.
Ou seja, ninguém declara um tipo AbstractPersistence e usa-o sem sabe qual sua implementação.
Mas qual a principal vantagem de não herdar e usar uma classe “utilitária”?
Obs: (Injetar a classe utilitária nas classes de persistência realmente seria uma ótima decisão, mas não usamos Spring, pelas restrições que citei no inicio do post).
[quote=xdraculax]Entendi.
Realmente abstração (AbstractPersistence) não é usada em nenhum lugar realmente como uma abstração.
Ou seja, ninguém declara um tipo AbstractPersistence e usa-o sem sabe qual sua implementação.
Mas qual a principal vantagem de não herdar e usar uma classe “utilitária”?
[/quote]
Várias vantagens mas a principal vantagem é desacoplamento.
Primeiro vc não vai usar o recurso de herança. Isso significa que vc pode herdar de outra coisa qq.
O recurso de herança é bala unica. se a usar uma vez, ja´era , portanto tem que se manter afastado de a usar o mais possivel.
Depois, herança tem a ver com categorias. Colocar um cara herdado AbstractPersistance não o categoriza realmente, mas do ponto de vista do java
sim. Faz sentido se vc tem algo como AbstractPersistance e depois herdando dele algo como XMLPErsistance, DBPersistance, CachePersistance. Vc está definindo um categoria de formas de persistencia. Mas fazer ProdutoPersistance, ClientePersistance, etc… não está categorizando nada, e pior, vc não consegue injetar mecanismos diferentes para a persistencia de produto, cliente, etc…
[quote]
Obs: (Injetar a classe utilitária nas classes de persistência realmente seria uma ótima decisão, mas não usamos Spring, pelas restrições que citei no inicio do post).[/quote]
A injeção é um principio que não depende de ferramentas ou containers. Passe o objeto no construtor do outro e pronto.
pior que eu ja usei assim… (é uma beleza :$)
ResultSet rGeral = ag.runSqlQuery("select * from produto where id_produto = " + cg.IntegerToSql(jTF_Produto.getText()));
mas o login eu usava preparedStatement…
e em conjunto usava:
[code] public static void BeginTrans() {
try {
conexao.setAutoCommit(false);
} catch (SQLException e) {
System.err.println(e.getMessage());
}
}
[/code]
e uma para Commit.
e para inserção eu fiz um framework leve usando classes anotadas. e jdbc puro