Conexões inativa no banco

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.

Você está fechando as EntityManager?

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.
}

}

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.

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

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

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

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.

Qual seria o correto ?

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.

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

É 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.

standalome

Seria isso ?

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

    return entityManagerFactory.createEntityManager();
}

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?

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.

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

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.

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.