| Autor |
Mensagem |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 11/02/2010 12:39:27
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
Pessoal, estou com o seguinte problema:
As classes de persistência de um projeto que estou trabalhando é em JDBC (não pode ser hibernate, por questões de desempenho).
Bem, nessas classes de persistência existem muitas operações com a mesma estrutura, como, por exemplo executar um Statement e retornar um ResultSet. Não faria sentido colocar o mesmo código repetido por todas as classes de persistência, portanto, coloquei o seguinte código na classe abstrata (AbstractePersistence):
Dessa forma eu não preciso toda vez que chamar um método em uma classe de persistência escrever o mesmo código repetitivo acima. Quando uma sub-classe quiser executar um ResultSet, é só chamar o método da super-classe e pronto.
O problema é: como o método retorna um ResultSet, e no mesmo método da classe abstrata, eu fecho a conexão (usamos um pool, portanto é obrigatório fechar a conexão, caso contrário o pool estoura), fechando a conexão, quem recebeu o ResultSet como retorno do método não vai conseguir obter os dados do ResultSet, pois o mesmo foi fechado.
Gostaria de saber a opnião de voces sobre estas decisões, e se tem algo melhor a ser feito. Pois dessa forma não está dando certo.
This message was edited 1 time. Last update was at 11/02/2010 14:01:36
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
|
|
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 10:01:09
|
pozzo
JavaEvangelist
Membro desde: 08/04/2006 11:07:20
Mensagens: 331
Localização: Curitiba
Offline
|
Ao invés de retornar o ResultSet, retorne outro objeto. Por exemplo um array de Object:
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 10:42:07
|
Bruno Laturner
JWizard
![[Avatar]](/images/avatar/5800ccd9514fd789d08e5831951aa6bc.jpg)
Membro desde: 18/02/2008 16:17:53
Mensagens: 2981
Offline
|
xdraculax wrote:As classes de persistência de um projeto que estou trabalhando é em JDBC (não pode ser hibernate, por questões de desempenho).
Em outras palavras, ninguém da empresa sabe usar Hibernate, certo?
|
A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 10:52:30
|
edmarr
Virtual Machine Man
![[Avatar]](/images/avatar/1f3f06e84308d0358db062ec5df47998.png)
Membro desde: 28/05/2009 09:52:36
Mensagens: 597
Offline
|
Tente PrepareStatement
http://java.sun.com/docs/books/tutorial/jdbc/basics/prepared.html
Bruno Laturner wrote:
xdraculax wrote:As classes de persistência de um projeto que estou trabalhando é em JDBC (não pode ser hibernate, por questões de desempenho).
Em outras palavras, ninguém da empresa sabe usar Hibernate, certo?
Bom tem que ver realmente , pois para se usar hibernate a modelagem do banco tem que estar bem definida , senao nosso amigo hibernate vai ficar
maluco maluco .
pozzo wrote:Ao invés de retornar o ResultSet, retorne outro objeto. Por exemplo um array de Object:
Retorne uma Coleção .
This message was edited 1 time. Last update was at 12/02/2010 12:29:29
|
SCJP 6 => Target finalized!
SCWCD => Target located!
Depois que seu problema tiver resolvido, vá no primeiro post, editar o Título adicionando a tag [RESOLVIDO] no final do Título .
Link para Pesquisa |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 11:02:53
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
Em outras palavras, ninguém da empresa sabe usar Hibernate, certo?
Não... em outras palavras usamos Hibernate "até dar uma dor" no sistema da central de processamento onde desempenho não é um requisito crítico.
Já no equipamento de campo onde recursos como memória e processamento são bem reduzidos, não usamos Hibernate, e sim JDBC.
Não podemos se dar ao luxo de ficar escrevendo nada em HSQL para ser traduzido para linguagem do banco (um over desnecessário).
Alem do +, não se tem pretenção de mudar o banco (Postgre) tão cedo, tão cedo mesmo.
Alem do +, se for pra usar o Hibernate executando query nativa, pra que usar Hibernate?
Se não tem nada de útil pra falar é melhor ficar calado.
This message was edited 2 times. Last update was at 12/02/2010 11:11:41
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 11:05:53
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
pozzo wrote:Ao invés de retornar o ResultSet, retorne outro objeto. Por exemplo um array de Object:
Huunn, é uma boa idéia, gostei da sua abordagem
Tente PrepareStatement
Cara, eu acho que não resolveria meu problema. Se eu usa-se o PS, ainda teria de retornar um ResultSet vindo de minda classe abstrata ok?
This message was edited 1 time. Last update was at 12/02/2010 11:10:38
|
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 11:18:43
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
Ae pessoal, lendo sobre algumas outras implementações da interface ResultSet, descobri que o JDBC também implementa conceitos de acesso a dados desconectados.
A classe CachedRowSetImpl é uma especialização da classe ResultSet que não usa ponteiro para os dados, e sim armazena-os em memória.
Assim, eu poderia retornar um objeto CachedRowSetImpl no retorno do método da classe abstrata.
Isso resolveria meu problema parcialmente, porque eu ainda teria problemas de consumo de recursos (se o colega fizer um select que retorne muitos resultados).
O que adotamos por enquanto foi:
As sub-classes liberam a conexão e result set's e statements.... quando achar uma solução melhor eu posto (ou se alguém souber e postar é bom também ).
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 12:37:46
|
Bruno Laturner
JWizard
![[Avatar]](/images/avatar/5800ccd9514fd789d08e5831951aa6bc.jpg)
Membro desde: 18/02/2008 16:17:53
Mensagens: 2981
Offline
|
Performance? Ok.
- Não é necessário fazer commits ou rollbacks em operações somente de leitura, como em consultas.
- Se você fechar ou fizer qualquer operação num Statament, o ResultSet dele irá fechar.
- Abrir e fechar conexões a cada método de consulta vai matar o teu banco de dados.
- Commits devem ser realizados somente quando a execução das classes do domínio finalizar. Você irá acabar com dados inconsistentes no banco se não fizer isto.
|
A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 12:43:29
|
ViniGodoy
Moderador
![[Avatar]](/images/avatar/1921493b5362e63fbe8983f4bd54157d.png)
Membro desde: 11/12/2006 08:22:01
Mensagens: 19489
Localização: Curitiba/PR
Offline
|
Bruno Laturner wrote:- Abrir e fechar conexões a cada método de consulta vai matar o teu banco de dados.
Para resolver esse problema, procure sobre pools de conexões, como o DBCP ou o C3P0. Mas para a sua aplicação, mantenha essa política de que ela deve trabalhar "desconectada" e não "conectada". O momento exato da desconexão física, deixe que um desses pools decida por você. Dê uma olhada no Spring. Ele é muito parecido com o JDBC e já implementa suporte a tudo isso. E trabalha de maneira muito similar ao CachedRowSetImpl. Ele também suporta batchUpdates e transações, transações aninhadas e stored procedures.
This message was edited 2 times. Last update was at 12/02/2010 12:45:13
|
@ViniGodoy - Lattes
Tem dúvidas de Java? Poste no fórum! Não respondo dúvidas de java via MP!
Ponto V! - Desenvolvimento de Jogos Profissional - @Pontov - Facebook
Projeto Towel - Swing de uma forma inteligente (Novo lar do ObjectTableModel e do Auto-Filtro).
Ei... você está usando DefaultTableModel no seu projeto??
Não faça isso! Veja: http://www.guj.com.br/posts/list/15/199067.java#1001295 |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 14:01:33
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
Bruno Laturner wrote:- Não é necessário fazer commits ou rollbacks em operações somente de leitura, como em consultas.
É, eu possi tirar isso dali. Não vai fazer diferença.
Bruno Laturner wrote:- Se você fechar ou fizer qualquer operação num Statament, o ResultSet dele irá fechar.
É exatamente esse o problema. Eu não posso liberar o statement na classe abstrata porque quando a sub-classe receber o resultado na verdade vai ter um ResultSet vázio (fechado).
Bruno Laturner wrote:- Abrir e fechar conexões a cada método de consulta vai matar o teu banco de dados.
O método getConnection() não cria conexão, ele vai pegar no pool (c3p0 - muito bom por sinal).
Bruno Laturner wrote:Commits devem ser realizados somente quando a execução das classes do domínio finalizar. Você irá acabar com dados inconsistentes no banco se não fizer isto.
Não pensei nissi ainda...
Vini... vou dar uma olhada no Spring para ver como ele faz isso...
This message was edited 2 times. Last update was at 12/02/2010 14:03:36
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 14:35:57
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline
|
xdraculax wrote:Pessoal, estou com o seguinte problema:
As classes de persistência de um projeto que estou trabalhando é em JDBC (não pode ser hibernate, por questões de desempenho).
Bem, nessas classes de persistência existem muitas operações com a mesma estrutura, como, por exemplo executar um Statement e retornar um ResultSet. Não faria sentido colocar o mesmo código repetido por todas as classes de persistência, portanto, coloquei o seguinte código na classe abstrata (AbstractePersistence):
Dessa forma eu não preciso toda vez que chamar um método em uma classe de persistência escrever o mesmo código repetitivo acima. Quando uma sub-classe quiser executar um ResultSet, é só chamar o método da super-classe e pronto.
só existe um problema com esse método : é POG.
Esse método mostra que a sua equipe não sabe trabalhar com JDBC. Então não fique ofendido quando desconfiamos que não saiba usar o hibernate.
E quando digo "usar" quero dizer "entender e fazer uso de features avançadas".
Simplesmente descarte esse método. Refactore seu codigo. É uma péssima ideia.
1) Use PreparedStatement SEMPRE
2) Abra e feche a conexão ao mesmo tempo que abre e fecha a transação. O Pool de conexão é inutil se vc não tem conceito de transação.
3) Monte o PreparedStatement , execute e leia o ResultSet num unico método. Não delegue esse tipo de controle.
4) Sempre feche os statements ao mesmo tempo que o resultSet.
5) menipule SQLException corretamente ( nada de e.printStackStrace)
só existe um motivo para não fechar o resultset e o retornar para ser usado depois: o padrão Fastlane Reader. Não é o seu caso.
Remodele seu codigo e terá menos problemas.
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 15:04:33
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
sergiotaborda wrote:Use PreparedStatement SEMPRE
Porque?
Eles são compilados para ficarem no cache do banco, mas não vi deferenças em testes que fiz com um Statement.
Você fez testes de desempenho? Ou só leu que sempre deve-se usar PreparedStatement?
sergiotaborda wrote: Abra e feche a conexão ao mesmo tempo que abre e fecha a transação. O Pool de conexão é inutil se vc não tem conceito de transação.
Transações são comitadas ao retornarem para o pool (quando é dado um close() na conexão) de qualquer jeito.
sergiotaborda wrote:
Monte o PreparedStatement , execute e leia o ResultSet num unico método. Não delegue esse tipo de controle.
Não quero fazer isso. Não vejo vantagem nenhuma nessa sua abordagem.
sergiotaborda wrote: Sempre feche os statements ao mesmo tempo que o resultSet.
Isso já está sendo feito pelos métodos de liberar, você não viu?
sergiotaborda wrote: menipule SQLException corretamente ( nada de e.printStackStrace)
Meu foco não é esse, depois que resolver o meu problema, ai sim vou fazer o trabalho mecânico de tratar a exception e logar.
POG?
Então quer dizer que se eu quero executar um Statement em vários locais de minhas classes de persistência, eu replico o mesmo código, com a mesma estrutura de try...cath rs.close stm.close..... em todos, da mesma forma; e colocar isso na classe abstrata onde todas as sub-classes executam o mesmo método da super-classe é POG?
Diga o que você faria então.
This message was edited 2 times. Last update was at 12/02/2010 15:07:15
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 12/02/2010 16:06:34
|
Bruno Laturner
JWizard
![[Avatar]](/images/avatar/5800ccd9514fd789d08e5831951aa6bc.jpg)
Membro desde: 18/02/2008 16:17:53
Mensagens: 2981
Offline
|
Acho que o pior problema desse método é que um cliente pode mandar uma String para ele e ferrar completamente com a base de dados da tua aplicação, ou derrubar o banco de dados inteiro. Procure saber sobre SQL Injection, e como o PreparedStatement ajuda a evitá-lo.
Faça os DAOs da tua aplicação retornarem somente o objeto ou uma coleção de objetos pesquisados, esses objetos sendo feitos a partir das classes do domínio da tua própria aplicação.
Exemplo de interfaces de métodos da classe de acesso ao banco:
Statements e ResultSets devem ficar encapsulados somente dentro do próprio método, nunca saindo para fora. Para fugir a essa regra, você tem que ter um bom motivo e 10x mais de cuidado ao deixar os teus objetos da camada de persistência fujam para outra camada.
|
A resposta acima foi achada em menos de 5 minutos no google.
The prisoner falls in love with his chains. --E.W. Dijkstra |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 19/02/2010 11:05:14
|
sergiotaborda
GUJ Expert
![[Avatar]](/images/avatar/b4a0e0fbaa9f16d8947c49f4e610b549.png)
Membro desde: 22/03/2005 20:57:48
Mensagens: 3420
Offline
|
xdraculax wrote:
sergiotaborda wrote:Use PreparedStatement SEMPRE
Porque?
Eles são compilados para ficarem no cache do banco, mas não vi deferenças em testes que fiz com um Statement.
Você fez testes de desempenho? Ou só leu que sempre deve-se usar PreparedStatement?
Não é um problema de performance. É um problema de segurança. Ele ajuda a evitar SQLInjection
sergiotaborda wrote: Abra e feche a conexão ao mesmo tempo que abre e fecha a transação. O Pool de conexão é inutil se vc não tem conceito de transação.
Transações são comitadas ao retornarem para o pool (quando é dado um close() na conexão) de qualquer jeito.
Se isso é verdade vc não está usando o conceito de transação. Transação necessita de um commit ou roolbak explicito.
Se vc deixa para comitar no close ( o que na realidade nunca acontece, ou se dá no commit ou se dá no execute se o autocommit está ligado) isso signfica que vc deve estar usando autocomit que é exatamente a antitese do conceito de transação.
sergiotaborda wrote:
Monte o PreparedStatement , execute e leia o ResultSet num unico método. Não delegue esse tipo de controle.
Não quero fazer isso. Não vejo vantagem nenhuma nessa sua abordagem.
Se vc não quer faze isso, então não se queixe que tem problemas.
Existe uma máxima que diz :"Não ha 'eu' em "arquitetura" (There is no I in architecture)
O que significa que o vc quer ou não quer é irrelevante.
POG?
Então quer dizer que se eu quero executar um Statement em vários locais de minhas classes de persistência, eu replico o mesmo código, com a mesma estrutura de try...cath rs.close stm.close..... em todos, da mesma forma; e colocar isso na classe abstrata onde todas as sub-classes executam o mesmo método da super-classe é POG?
sim.
Diga o que você faria então.
Já lhe disse o que faria.
Colocar métodos genéricos em classes abstratas parece legal, mas precisa aprender quando parar. Este é um caso em que deve parar de fazer isso.
This message was edited 1 time. Last update was at 19/02/2010 11:07:08
|
Criando sua própria API de Validação
Blog do MiddleHeaven |
|
|
 |
![[Post New]](/templates/default/images/icon_minipost_new.gif) 19/02/2010 13:51:54
|
xdraculax
Java Ninja
Membro desde: 12/01/2009 16:12:54
Mensagens: 284
Offline
|
Sim é POG? Explique porque ou isso é um "EU acho que é POG"?
Não é POG, é divergência de opnião. E você não tem uma justificativa plausível, portanto, sem comentários.
Pra mim, repetir a mesma estrutura de código por n métodos de classes de persistência é que é POG. E foi o que você disse que faria.
Quanto a segurança, eu até entendo isso; mas quem vai escrever os SQL são programadores, e não "paes & mães".
O sistema não tem entradas inseridas por usuários, tudo é gerado por um Hardware. Então esse conceito de segurança, neste contexto, não faz sentido.
Se o programador é burro pra escrever um SQL desastroso, ele vai fazer isso em qualquer outra situação.
Você simplesmente leu que deve-se usar PS em todas as situações e acreditou. Nem se ocupou em fazer testes para ver se realmente faz sentido utilizá-lo em todas as situações.
Com relação a dar um commit no retorno da conexão para o pool realmente concordo com você. Não é muito inteligente.
This message was edited 3 times. Last update was at 19/02/2010 15:13:30
|
-Atenha-se a resolver o problema, e não criticar opiniões.
-Você percebe que está programando d+, quando está escrevendo identado!
-Não precisa estar certo, basta acreditar. |
|
|
 |
|
|