Problema com conexão no banco

10 respostas
R

Caused by: org.hibernate.exception.GenericJDBCException: Cannot open connection at org.hibernate.exception.SQLStateConverter.handledNonSpecificException(SQLStateConverter.java:126) at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:114) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:52) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:449) at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167) at org.hibernate.jdbc.AbstractBatcher.prepareQueryStatement(AbstractBatcher.java:161) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:1573) at org.hibernate.loader.Loader.doQuery(Loader.java:696) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:259) at org.hibernate.loader.Loader.doList(Loader.java:2228) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2125) at org.hibernate.loader.Loader.list(Loader.java:2120) at org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:401) at org.hibernate.hql.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:361) at org.hibernate.engine.query.HQLQueryPlan.performList(HQLQueryPlan.java:196) at org.hibernate.impl.SessionImpl.list(SessionImpl.java:1148) at org.hibernate.impl.QueryImpl.list(QueryImpl.java:102) at br.com.cauirs.sgv.model.dao.DuplicataHibernateDao.getList(DuplicataHibernateDao.java:58) ... 31 more Caused by: java.sql.SQLException: An attempt by a client to checkout a Connection has timed out. at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:106) at com.mchange.v2.sql.SqlUtils.toSQLException(SqlUtils.java:65) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:527) at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) at org.hibernate.connection.C3P0ConnectionProvider.getConnection(C3P0ConnectionProvider.java:78) at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446) ... 45 more Caused by: com.mchange.v2.resourcepool.TimeoutException: A client timed out while waiting to acquire a resource from com.mchange.v2.resourcepool.BasicResourcePool@407dd4 -- timeout at awaitAvailable() at com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable(BasicResourcePool.java:1317) at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:557) at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) ... 48 more

Alguém sabe resolver? To perdido… ta tudo parado aqui por causa desse erro :shock:

10 Respostas

F

eae…

vc poderia postar parte do seu codigo que faz a conexao…

fica mais facil descobrir!!!

flw

R

Tenho um DAO para cada entidade um exemplo de como pesquiso, adiciono e removo

Ta pegando esse erro de conexão, acho que está ocorrendo vazamentos de conexões, ou sessões que ficam abertas (preciso fechar a sessão que eu abro ali, como faço?) .. Alguma sugestão??

Na pesquisa eu abro a sessão para retornar a lista, onde ela será fechada?? return HibernateUtil.getSessionFactory(id).openSession().createQuery("from Grupo").list();

@SuppressWarnings("unchecked")
	public List<Grupo> getList(String id) throws Exception {
		
		try {
			
			return HibernateUtil.getSessionFactory(id).openSession().createQuery("from Grupo").list();
		
		} catch(GenericJDBCException e) {
			
			System.out.println("---------ERRO NA CONEXÃO---------");
			e.printStackTrace();
			System.out.println("---------FIM DO LOG DO ERRO NA CONEXÃO---------");
			throw new DaoException("Não foi possível acessar o servidor. Tente novamente em alguns minutos.", e);
			
		} catch(Exception e) {
			
			throw new FlexException("Ocorreu um erro não reconhecido pelo sistema.Entre em contato com o suporte para solucionar esse problema.", e);
			
		}
		
	}

	public void remove(String id, Grupo grupo) throws Exception {
		
		try {
			
			this.session = HibernateUtil.getSessionFactory(id).openSession();
			this.tx = this.session.beginTransaction();
			
			this.session.delete(grupo);
			this.session.flush();
			tx.commit();
			
		} catch(GenericJDBCException e) {
			
			this.tx.rollback();
			
			System.out.println("---------ERRO NA CONEXÃO---------");
			e.printStackTrace();
			System.out.println("---------FIM DO LOG DO ERRO NA CONEXÃO---------");
			throw new DaoException("Não foi possível acessar o servidor. Tente novamente em alguns minutos.", e);
			
		} catch (ConstraintViolationException e) {
			
			this.tx.rollback();
			
			throw new DaoException(
			"Não é possível a exclusão.Pois esse registro está sendo usado em outro(s) cadastro(s).", e);
		
		} catch(Exception e) {
			
			this.tx.rollback();
			
			throw new FlexException("Ocorreu um erro não reconhecido pelo sistema.Entre em contato com o suporte para solucionar esse problema.", e);
			
		}
		
	}

	public void save(String id, Grupo grupo) throws Exception {
		
		try {
			
			this.session = HibernateUtil.getSessionFactory(id).openSession();
			this.tx = this.session.beginTransaction();
			
			this.session.saveOrUpdate(grupo);
			this.session.flush();
			tx.commit();
			
		} catch(GenericJDBCException e) {
			
			this.tx.rollback();
			
			System.out.println("---------ERRO NA CONEXÃO---------");
			e.printStackTrace();
			System.out.println("---------FIM DO LOG DO ERRO NA CONEXÃO---------");
			throw new DaoException("Não foi possível acessar o servidor. Tente novamente em alguns minutos.", e);
			
		} catch(Exception e) {
			
			this.tx.rollback();
			
			throw new FlexException("Ocorreu um erro não reconhecido pelo sistema.Entre em contato com o suporte para solucionar esse problema.", e);
			
		}
		
	}
F

Você tem que fechar as conexões, cara. Dá timeout porque elas ficam muito tempo abertas. O problema é que se você fechar, alguém pode tentar pegar aquele session e vai dar o erro “session was closed”. Como você não tá usando nenhum framework que gerencie a sessão, sugiro que implemente um Filter usando o padrão Open Session in View. Dá uma olhada nesse link: https://www.hibernate.org/43.html?cmd=prntdoc
Mas se puder, usa um frameworkzinho pra quebrar esse galho, como o Spring. É muito mais prático e limpo.

R

Sim, eu sei das sessões, mas estou há 4 meses sem o Spring gerenciamento manualmente e funciona corretamente e o pior:

Olhem só que estranho:

Tenho uma versão anterior, e fiz a versão nova (com algumas pequenas alterações).

Coloquei a versão anterior em um domínio, e a versão nova em outro.Faço dar pau no novo (acessando de varias instancias do browser e varios pc’s).Vou no sistema velho e consigo usar normalmente. OBS: Usam o mesmo banco de dados! ( o banco de dados está no servidor do anterior )

Porém, pela manhã tentei colocar o sistema novo no domínio do anterior (para verificar se não havia problemas do sistema acessar banco de dominio diferente) e deu erro, enquanto o antigo continuava funcionando sempre!

Então, não é problema no banco de dados,

Ao reiniciar o tomcat do servidor (do novo) funciona normalmente: Problema está localizado no Java do sistema novo.

Possibilidades:

Sessões abertas: Se fosse isso não estaria com problema no anterior também?? Isso é o que me intriga…
Vou verificar o que foi modificado no DAO para esses problemas acontecerem…

Mais algum teste que posso fazer?

OBS: Não quero usar Spring (porque preciso criar a factory em runtime para usar mais de um banco… ja tentei fazer isso com Spring mas não deu certo), como estou com o sistema em produção preciso liberar essa versão nova se possível para amanhã.

OBS2:Preciso de algo que comprove que o problema está nas sessões abertas para “perder” tempo implementando um filtro, já que, o anterior ESTA funcionando sem o uso do mesmo. Ja tentei usar o Hibernate Profiler mas sem sucesso…

F

Sessões abertas: Se fosse isso não estaria com problema no anterior também?? Isso é o que me intriga…
Vou verificar o que foi modificado no DAO para esses problemas acontecerem…

O timeout pode levar até horas para ocorrer após sua aplicação ser levantada. Além disso o código da versão que funciona provavelmente não é o mesmo da versão que dá erro.

Esse timeout pode ser do c3p0 ou do seu banco. Experimenta diminuir o timeout do C3p0 pra ver. Na pior das hipóteses deixa as duas aplicações abertas no mesmo servidor e testa no dia seguinte :smiley:

Com JPA é mamão com açúcar, como diria meu professor. Você declara duas persistence-unit no persistence.xml e no código você referencia a persistence-unit que precisar. Se estiver usando um servidor de aplicação ainda pode deixá-lo gerenciar essas benditas conexões.


OBS2reciso de algo que comprove que o problema está nas sessões abertas para “perder” tempo implementando um filtro, já que, o anterior ESTA funcionando sem o uso do mesmo. Ja tentei usar o Hibernate Profiler mas sem sucesso…

Você não vai perder tempo. O código transacional vai ficar num único ponto, assim você não vai copiar e colar código pra cada método novo.

R

Então acho que o código do sistema anterior está funcionando… pois até agora não houve nenhuma reclamação…
E o gerenciamento das sessões era feito da mesma maneira :S

E, em relação a esse exemplo JPA tem algum código como exemplo (estou aqui fazendo testes para solucionar o meu problema, não vou conseguir procurar agora se tiver para facilitar melhor, senão procuro depois…)

R

Após uma tarde toda sem achar solução…

A noite decidi realizar alguns testes: voltar a versão antiga e ir adicionando as classes da nova aos poucos para ver aonde estava o “erro”.

Achei e estava nesse relacionamento ManyToMany…

Na classe Usuario:

@ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "usuario_vendedor", joinColumns = { @JoinColumn(name = "idusuario", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "idvendedor", nullable = false, updatable = false) }) private Set<Vendedor> vendedores;

Na classe Vendedor:

@ManyToMany(fetch = FetchType.LAZY) @JoinTable(name = "usuario_vendedor", joinColumns = { @JoinColumn(name = "idusuario", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "idvendedor", nullable = false, updatable = false) }) private Set<Usuario> usuarios = new HashSet<Usuario>(0);

Como posso substituir isso para não causar esses problemas de conexão?

F

O mapeamento não tem relação nenhuma com o problema de conexão. Suas opções são as seguintes:

1 - Usa o getCurrentSession ao invés do openSession
2 - Implementa o Open Session in View
3 - Usa Spring
4 - Usa CMT(Container-Managed Transactions)

Eu prefiro a opção 4, que é simples de implementar e provavelmente a mais poderosa. Mas você vai precisar de um servidor de aplicação como o JBoss.

R

Como não tenho JBoss, vou fazer alguns testes com Spring.

O problema do Spring é que não tenho experiência com ele, e precisaria de algum tempo (e também já tive uma experiência negativa de uma semana tentando configurar para acessar mais de um banco em tempo de execução e não obter resultado), mas sei que ele é muito útil nessa questão de gerenciamento de transações.

Usar o getCurrentSession e o Open Session in View seriam soluções mais rápidas, porém isso não seria “tapar o sol com uma peneira”?

R

Vamos recomeçar e ir por partes:

Esse problema acontece por:

1 - Abro sessões e não fecho (essas conexões ficam abertas no pool)
2 - O pool tem um limite máximo, todas conexões que excederem ficam na fila
3 - Como tenho o timeout configurado no properties ele gera essa exceção por exceder o tempo de timeout na fila

Pergunta 1: Se estou certo na afirmação acima, para resolver o problema preciso “apenas” fechar todas sessões (conexões) que abro?

Das soluções que você apresentou não posso usar CMT (não uso JBoss), nem Open Session in View (pois defino os bancos em runtime, não teria como passar isso na inicizalição da servlet do filtro).Spring apenas em ultimo caso.

Então me restou usar getCurrentSession, ao realizar um teste aqui:

1 - Ao realizar o login abrem-se 17 sessões ( chamadas ao banco )
2 - Substitui em 3 das consultas o openSession para o getCurrentSession, e obtive 16 sessões abertas.

Pergunta 2: Porque abriu apenas 1 a menos? Não seria 15 sessões o numero correto? O correto não seria na primeira vez que usar o getCurrentSession iria criar essa sessão no contexto, e após isso iria utilizar sempre a mesma? ( dizem que uma sessão por aplicação não é bom mas quando eu sei que posso fechá-la? )

Criado 2 de março de 2010
Ultima resposta 4 de mar. de 2010
Respostas 10
Participantes 3