Conexões inativa no banco

17 respostas
aszarael

Boa tarde pessoal,

estou usando JPA + Hibernate, para realizar consultas no banco.
Com isso utilizo um pool de conexão, porem, após executar o no banco oracle, está ficando conexões inativas, o que muita vezes acaba derrubando o banco.

Alguém sabe o porque disso ?

Utilizo o método de conexão com o banco

public static EntityManager getEntityManager(){
	if (entityManagerFactory == null){
    		entityManagerFactory = Persistence.createEntityManagerFactory("BD_CONNECT_OP");
    }

    return entityManagerFactory.createEntityManager();
}

grato.

17 Respostas

CWeiler

Você está fechando as EntityManager?

aszarael

Sim, já fiz o teste fechando, sem fechar, e deu o mesmo resultado de qualquer modo.
segue a minha classe de consulta.

package com.br.dao;

import java.util.List;
import java.util.logging.Logger;

import javax.persistence.EntityManager;

import javax.persistence.Query;

import com.br.model.V$SESSION;

public class V$SESSIONDao {

private Logger        logger = Logger.getLogger("br.com.log");  
private StringBuilder vSQL   = new StringBuilder();
private EntityManager entityManager;

/* Metodo de Cria��o do Entity Manager */
private EntityManager getEntityManager(String pUsuario, String pSenha, String pInstancia){
	return ManagerEntityManager.getEntityManager(pUsuario,pSenha,pInstancia);
}

/* Metodo de consulta no banco de dados */
private List<V$SESSION> consultar(List<String> pColunas, List<String> pValores, 
								  String pUsuario, String pSenha, String pInstancia){
	
	entityManager = getEntityManager(pUsuario,pSenha,pInstancia);
	vSQL.append("from V$SESSION as v$session");
	
	if (pColunas != null){
		vSQL.append(" WHERE ");
		
		for (int i = 0; i < pColunas.size(); i++){
			if (i==0){
				vSQL.append(" " + pColunas.get(i).toString() + " = '" + pValores.get(i).toString() + "'");
			}else{
				vSQL.append(" AND " + pColunas.get(i).toString() + " = '" + pValores.get(i).toString() + "'");
			}
		}
	}

	vSQL.append(" ORDER BY USERNAME ASC");
	
	logger.info("Consulta : " + vSQL);
	Query vQuery = entityManager.createQuery(vSQL.toString());		
	@SuppressWarnings("unchecked")
	List<V$SESSION> listaUpLoad = vQuery.getResultList();
	entityManager.close();
	return listaUpLoad;		
}

public List<V$SESSION> select(List<String> pColunas, List<String> pValores, 
		  					  String pUsuario, String pSenha, String pInstancia){
	return consultar(pColunas,pValores,pUsuario,pSenha,pInstancia);
}

public void closeConection(){
//	entityManager.clear();
//	entityManager.close();

// está comentado, pois, coloquei direto na consulta para teste.
}

}

CWeiler

Este é o único local onde as EM são criadas e fechadas?

O código está executando sem erros em todas as vezes? Qualquer erro no método consultar irá deixar uma EM sem ser fechada.

peczenyj

vc não usa um pool de conexões como C3P0 ?

aszarael

Sim, está executando sem erro algum, já está funcionando, somente aparentemente está deixando sessões inativas no banco;

aszarael

Sim, utilizo, está no meu xml

<properties>
  <property name="hibernate.connection.driver_class" value="oracle.jdbc.OracleDriver"/>
  <property name="hibernate.dialect" value="org.hibernate.dialect.OracleDialect"/> 
  <property name="hibernate.format_sql" value="true"/>
  
  <!-- Configuração para não perder conexão -->  
 <property name="hibernate.c3p0.min_size" value="1"/>    
 <property name="hibernate.c3p0.max_size" value="1"/>    
 <property name="hibernate.c3p0.timeout" value="3"/> 
 <property name="hibernate.c3p0.maxIdle" value="1"/>  
 <property name="hibernate.c3p0.minEvictableIdleTimeMillis" value="1"/>  
 <property name="hibernate.c3p0.idle_test_period" value="0"/>  
 <property name="hibernate.c3p0.acquire_increment" value="2"/>       
</properties>

Veja a parametização

CWeiler

O c3p0 está configurado para iniciar com 1 conexão ativa, e manter no máximo 1 conexão.

Aparentemente está ocorrendo duplicação de sessões do c3p0.

Obs. o acquire_increment não bate com o resto da configuração.

aszarael

Qual seria o correto ?

CWeiler

Sobre o acquire_increment? Não tem “certo”, ele apenas não bate com a configuração, você está pedindo para ele fazer um incremente de 2 conexões, mas o máximo é 1, pode apenas remover ou configurar como 1. Mas isso não é o problema, o seu problema provavelmente são sessões perdidas.

Quando você usa um pool, ao fechar uma conexão no código ela não é realmente “fechada”, ela é devolvida para o pool.

aszarael

Existe alguma maneira, de liberar, pq no banco fica como inativa, e isso, está deixando lotando as sessões e acaba derrubando o banco.

CWeiler

É aplicação web ou standalone?

Se for aplicação web, o ideal é delegar isso para o servidor, melhor ainda é utilizar o pool do próprio servidor.

Se for standalone você precisa fechar o entityManagerFactory.

aszarael

standalome

Seria isso ?

public static EntityManager getEntityManager(){
	
	entityManagerFactory.close();
	
	if (entityManagerFactory == null){
    		entityManagerFactory = Persistence.createEntityManagerFactory("BD_CONNECT_OP");
    }

    return entityManagerFactory.createEntityManager();
}
CWeiler

O objetivo de um pool é para economia de recursos de aquisição de novas conexões, então você deveria criar o factory na primeira vez necessária, e fechá-lo quando a aplicação for encerrada. Aparentemente o seu problema está realmente nesta estrutura, pois os factories estão sendo recriados sem necessidade, precisa descobrir a causa.

Detalhe: as EMs ainda precisam ser fechadas após cada uso!

Outra pergunta: Esta aplicação tem vida curta? Executa, responde e sai?

aszarael

Na verdade, eu cria uma e vou reutilizando conforme o codigo, somente se ela estiver vazia, eu crio outra.
Mais, consegui resolver o problema, verificando se a factory, está aberta, ai encerro ela e crio de novo, isso liberada as inativas do banco.

javaflex

Hibernate já é um monstro, você está recriando o objeto mais pesado dele, o session factory? Se você quer efetivamente fechar a conexão com o banco de dados pra ficar usando sob demanda, feche a connection de verdade e não só a sessão gerenciada pelo Hibernate. De momento não consigo te passar como se acessa a connection pelo Hibernate do Java, mas pra te servir de pista, no C# é assim:

session.Connection.Close();
  session.Close();
  session.Dispose();

No mais, pesquisando pode achar tópicos como este: Pq o maldito Hibernate não fecha a conexão?

Como está usando JPA, pra pegar a connection: http://stackoverflow.com/questions/3493495/getting-database-connection-in-pure-jpa-setup

aszarael

Então, descobri que na verdade, não a problema no hibernate, e sim no banco, pois acabei executando o mesmo processo em outro banco, melhor configurado pelo DBA, e não apresentou o problema.
Fiz uma tratativa e aparentemente está funcionando de acordo agora.

Obrigado pela ajuda.

javaflex

Bom que tenha resolvido o problema. Só não espere que sempre terá esse cenário garantido, se de fato fechar a conexão com o banco ficará independente disso.

Criado 29 de novembro de 2016
Ultima resposta 30 de nov. de 2016
Respostas 17
Participantes 4