Conexão não sendo fechada, mesmo com o close() (iBatis)

11 respostas
A

Então pessoal, estou com um sério problema aqui. A minha aplicação mantém muitas conexões em aberto, a elas chegam a atingir o número máximo especificado e o sistema trava geral.

Eu faço o acompanhamento via sqlPlus (estou usando Oracle), e percebo que ao logar no sistema, por exemplo, o sistema abre uma conexão com o banco e não a fecha. Para cada SQL que eu rodo, uma conn é aberta e não fechada, até atingir o limite e travar tudo.

Aqui vão os detalhes do sistema:

  • Apache iBatis
  • Apache Tomcat 5.5.29
  • Oracle 9i

Configuração do iBatis:
sqlMapConfig.xml:

...
<settings cacheModelsEnabled="true" enhancementEnabled="true"
		lazyLoadingEnabled="true" maxRequests="500" maxSessions="250"
		maxTransactions="50" useStatementNamespaces="false" />
...
<transactionManager type="JDBC">
		<dataSource type="SIMPLE">
			<property name="JDBC.Driver" value="oracle.jdbc.driver.OracleDriver" />
			<property name="JDBC.ConnectionURL" value="jdbc:oracle:thin:@xxx:1521:yyyy" />
			<property name="JDBC.Username" value="teste" />
			<property name="JDBC.Password" value="xxxxx" />
		</dataSource>
	</transactionManager>
...

SqlMapSingleton.java (responsável pro retornar um objeto de conexão):

package com.gesplan.dao.singleton;

import java.io.Reader;
import java.sql.DriverManager;
import java.sql.SQLException;

import javax.servlet.ServletContext;

import com.gesplan.gsframework.domain.GSConf;
import com.ibatis.common.resources.Resources;
import com.ibatis.sqlmap.client.SqlMapClient;
import com.ibatis.sqlmap.client.SqlMapClientBuilder;
import com.ibatis.sqlmap.client.SqlMapSession;

public class SqlMapSingleton {
	
	private static final SqlMapClient sqlMap;
	
	static {
		try {			
			String resource = "com/gesplan/configuration/sqlMap-config.xml";
			Reader reader = Resources.getResourceAsReader(resource);			
			sqlMap = SqlMapClientBuilder.buildSqlMapClient(reader);			
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException ("Error initializing SqlMapSingleton class. Cause: " + e);
		}
	}
	
	/**
	 * Para IceFaces
	 * @return
	 */
	public static SqlMapSession getSqlMapInstance() {
                //GSConf me retorna os parametros para acha o BD, sobrepondo o que está no sqlMapConfig.xml
		GSConf gsconf = new GSConf();
		try {
			return sqlMap.openSession((DriverManager.getConnection(gsconf.getURL(), gsconf.getDbUsername(), gsconf.getDbPassword())));
		} catch (SQLException e) {
			e.printStackTrace();
			
			return sqlMap.openSession();
		}		
	}	
}

Um exemplo de código usando a conexão, SqlMapDespesasFixas.java:

package com.gesplan.gsbudget.dao.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import org.springframework.dao.DataAccessException;

import com.gesplan.dao.singleton.SqlMapClientDaoSupportGesplan;
import com.gesplan.dao.singleton.SqlMapSingleton;
import com.gesplan.gsbudget.dao.IntDespesasFixas;
import com.gesplan.gsbudget.domain.DespesasFixasId;
import com.gesplan.gsbudget.domain.DespesasFixasQuantidade;
import com.ibatis.sqlmap.client.SqlMapSession;

public class SqlMapDespesasFixas extends SqlMapClientDaoSupportGesplan
		implements IntDespesasFixas {

	@SuppressWarnings("unchecked")
	public ArrayList<DespesasFixasId> getListData(Integer idUnidadeNegocio,
			Integer idEmpresa, Integer idCenario, Integer idMaster)			
			throws DataAccessException, SQLException {
		SqlMapSession sqlMap = SqlMapSingleton.getSqlMapInstance();

		HashMap<String, String> params = new HashMap<String, String>();
		params.put("idUnidadeNegocio", idUnidadeNegocio.toString());
		params.put("idEmpresa", idEmpresa.toString());
		params.put("idCenario", idCenario.toString());
		params.put("idMaster", idMaster.toString());
		
		ArrayList<DespesasFixasId> retorno = (ArrayList) sqlMap.queryForList("getAllData" + getBanco(),params);
		sqlMap.close();
		return retorno;
	}

	@SuppressWarnings("unchecked")
	public ArrayList<DespesasFixasQuantidade> getListDataQuantidade(
			Integer idUnidadeNegocio, Integer idEmpresa, Integer idCenario,
			Integer idMaster) throws DataAccessException, SQLException {
		
		SqlMapSession sqlMap = SqlMapSingleton.getSqlMapInstance();
		
		HashMap<String, String> params = new HashMap<String, String>();
		params.put("idUnidadeNegocio", idUnidadeNegocio.toString());
		params.put("idEmpresa", idEmpresa.toString());
		params.put("idCenario", idCenario.toString());
		params.put("idMaster", idMaster.toString());
		
		ArrayList<DespesasFixasQuantidade> retorno = (ArrayList) sqlMap.queryForList("getAllDataQuantidade"
				+ getBanco(), params);
		
		sqlMap.close();
		return retorno;
	}

	public void insertOrcarConta(Integer idEmpresa, String idCO, String idCC,
			Integer idMoeda, Integer idUnidadeNegocio, Integer idCenario,
			Long idPrj) throws DataAccessException, SQLException {
		SqlMapSession sqlMap = SqlMapSingleton.getSqlMapInstance();
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("idEmpresa", idEmpresa);
		params.put("idCO", idCO);
		params.put("idCC", idCC);
		params.put("idMoeda", idMoeda);
		params.put("idUnidadeNegocio", idUnidadeNegocio);
		params.put("idCenario", idCenario);
		params.put("idPrj", idPrj);
		sqlMap.insert("insertOrcarConta" + getBanco(), params);
		sqlMap.close();
	}

	public void updateValores(Integer idEmpresa, String idCO, String idCC,
			Integer idMoeda, Integer idUnidadeNegocio, Integer idCenario,
			Long idPrj, Double vlValorJan, Double vlValorFev,
			Double vlValorMar, Double vlValorAbr, Double vlValorMai,
			Double vlValorJun, Double vlValorJul, Double vlValorAgo,
			Double vlValorSet, Double vlValorOut, Double vlValorNov,
			Double vlValorDez) throws DataAccessException, SQLException {
		SqlMapSession sqlMap = SqlMapSingleton.getSqlMapInstance();
		HashMap<String, Object> params = new HashMap<String, Object>();
		params.put("idEmpresa", idEmpresa);
		params.put("idCO", idCO);
		params.put("idCC", idCC);
		params.put("idMoeda", idMoeda);
		params.put("idUnidadeNegocio", idUnidadeNegocio);
		params.put("idCenario", idCenario);
		params.put("idPrj", idPrj);
		params.put("vlValorJan", vlValorJan);
		params.put("vlValorFev", vlValorFev);
		params.put("vlValorMar", vlValorMar);
		params.put("vlValorAbr", vlValorAbr);
		params.put("vlValorMai", vlValorMai);
		params.put("vlValorJun", vlValorJun);
		params.put("vlValorJul", vlValorJul);
		params.put("vlValorAgo", vlValorAgo);
		params.put("vlValorSet", vlValorSet);
		params.put("vlValorOut", vlValorOut);
		params.put("vlValorNov", vlValorNov);
		params.put("vlValorDez", vlValorDez);
		sqlMap.update("updateValores" + getBanco(), params);
		sqlMap.close();
	}	
}

Reparem que para cada acesso ao SGBD, eu crio e fecho uma conexão.

Onde está o meu erro?

Obrigado!

11 Respostas

rafaelglauber

coloque tudo num bloco try finally e coloque o close no finally, apos essa mudança verifique se permanece ainda sem fechar a conexão.

A

Modifiquei a classe da conexão que mostrei antes, ela ficou assim:

package com.gesplan.gsbudget.dao.impl;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import org.springframework.dao.DataAccessException;

import com.gesplan.dao.singleton.SqlMapClientDaoSupportGesplan;
import com.gesplan.dao.singleton.SqlMapSingleton;
import com.gesplan.gsbudget.dao.IntDespesasFixas;
import com.gesplan.gsbudget.domain.DespesasFixasId;
import com.gesplan.gsbudget.domain.DespesasFixasQuantidade;
import com.ibatis.sqlmap.client.SqlMapSession;

public class SqlMapDespesasFixas extends SqlMapClientDaoSupportGesplan
		implements IntDespesasFixas {

	@SuppressWarnings("unchecked")
	public ArrayList<DespesasFixasId> getListData(Integer idUnidadeNegocio,
			Integer idEmpresa, Integer idCenario, Integer idMaster)
			throws DataAccessException, SQLException {
		SqlMapSession sqlMap = null;
		ArrayList<DespesasFixasId> retorno;
		try {
			sqlMap = SqlMapSingleton.getSqlMapInstance();

			HashMap<String, String> params = new HashMap<String, String>();
			params.put("idUnidadeNegocio", idUnidadeNegocio.toString());
			params.put("idEmpresa", idEmpresa.toString());
			params.put("idCenario", idCenario.toString());
			params.put("idMaster", idMaster.toString());
			
			retorno = (ArrayList) sqlMap.queryForList(
					"getAllData" + getBanco(), params);
		} finally {
			sqlMap.close();
		}
		return retorno;
	}

	@SuppressWarnings("unchecked")
	public ArrayList<DespesasFixasQuantidade> getListDataQuantidade(
			Integer idUnidadeNegocio, Integer idEmpresa, Integer idCenario,
			Integer idMaster) throws DataAccessException, SQLException {
		SqlMapSession sqlMap = null;
		ArrayList<DespesasFixasQuantidade> retorno;
		try {
			sqlMap = SqlMapSingleton.getSqlMapInstance();
			
			HashMap<String, String> params = new HashMap<String, String>();
			params.put("idUnidadeNegocio", idUnidadeNegocio.toString());
			params.put("idEmpresa", idEmpresa.toString());
			params.put("idCenario", idCenario.toString());
			params.put("idMaster", idMaster.toString());
			
			retorno = (ArrayList) sqlMap.queryForList("getAllDataQuantidade"
					+ getBanco(), params);

		} finally {
			sqlMap.close();
		}
		return retorno;
	}

	public void insertOrcarConta(Integer idEmpresa, String idCO, String idCC,
			Integer idMoeda, Integer idUnidadeNegocio, Integer idCenario,
			Long idPrj) throws DataAccessException, SQLException {
		SqlMapSession sqlMap = null;
		try {
			sqlMap = SqlMapSingleton.getSqlMapInstance();
			HashMap<String, Object> params = new HashMap<String, Object>();
			params.put("idEmpresa", idEmpresa);
			params.put("idCO", idCO);
			params.put("idCC", idCC);
			params.put("idMoeda", idMoeda);
			params.put("idUnidadeNegocio", idUnidadeNegocio);
			params.put("idCenario", idCenario);
			params.put("idPrj", idPrj);
			sqlMap.insert("insertOrcarConta" + getBanco(), params);
		} finally {
			sqlMap.close();
		}
	}

	public void updateValores(Integer idEmpresa, String idCO, String idCC,
			Integer idMoeda, Integer idUnidadeNegocio, Integer idCenario,
			Long idPrj, Double vlValorJan, Double vlValorFev,
			Double vlValorMar, Double vlValorAbr, Double vlValorMai,
			Double vlValorJun, Double vlValorJul, Double vlValorAgo,
			Double vlValorSet, Double vlValorOut, Double vlValorNov,
			Double vlValorDez) throws DataAccessException, SQLException {
		SqlMapSession sqlMap = null;
		try {
			sqlMap = SqlMapSingleton.getSqlMapInstance();
			HashMap<String, Object> params = new HashMap<String, Object>();
			params.put("idEmpresa", idEmpresa);
			params.put("idCO", idCO);
			params.put("idCC", idCC);
			params.put("idMoeda", idMoeda);
			params.put("idUnidadeNegocio", idUnidadeNegocio);
			params.put("idCenario", idCenario);
			params.put("idPrj", idPrj);
			params.put("vlValorJan", vlValorJan);
			params.put("vlValorFev", vlValorFev);
			params.put("vlValorMar", vlValorMar);
			params.put("vlValorAbr", vlValorAbr);
			params.put("vlValorMai", vlValorMai);
			params.put("vlValorJun", vlValorJun);
			params.put("vlValorJul", vlValorJul);
			params.put("vlValorAgo", vlValorAgo);
			params.put("vlValorSet", vlValorSet);
			params.put("vlValorOut", vlValorOut);
			params.put("vlValorNov", vlValorNov);
			params.put("vlValorDez", vlValorDez);
			sqlMap.update("updateValores" + getBanco(), params);
		} finally {
			sqlMap.close();
		}
	}

}

E não deu diferença alguma :frowning:

Codifiquei algo errado?

Obrigado mesmo Rafael.

rafaelglauber

tente retirar o static do: public static SqlMapSession getSqlMapInstance()

A

Retirei, e houve melhora, mas pouco significativa.

Não to conseguindo entender o que ocorre, me parece inexato. Antes, cerca de 50% das conexões eram fechadas e o restante ficava aberto. Agora, com o try / finally e aquele método sem static, melhorou, esse índice caiu para 30% das conexões abertas permanecem abertas mesmo após o close.

Cara, vc pode me explicar o porque desse static? Não consigo entender pq isso ajudou!

E será que consigo melhorar ainda mais isso?

Muito obrigado mesmo!

rafaelglauber

Volta o static que pedi que tirasse e remova o “final” de “private static final SqlMapClient sqlMap;”

se isso funcionar te explico o que pensei, pois não tenho certeza que irá funcionar!!!

:smiley:

A

:smiley:
Coloquei o static e tirei o final, melhorou um monte!

Agora, depois de navegar um monte pelo sistema, só ficam 2 ou 3 conexões lá… Bem menos que as 12 ~ 18 antes do primeiro tete que vc sugeriu.

Me conta!

A

E aí pessoal, ainda não cheguei a 100% de conexões fechadas, será que isso é possível?

Rafael, consegue me explicar o porque do final?

Obrigado!

A

Alguém?

rafaelglauber

Sobre o final a esplicação é simples: um atributo final, depois de inicializado não pode mais ser mudado! agora sobre o fato das conexões não fecharem 100% teria que executar o seu código, pois não tenho dominio ainda para somente lendo compreender a situação totalmente, desculpe, mas estou sem tempo para fazer isso no momento, espero ter ajudado em alguma coisa.

:frowning:

rafaelglauber

rafaelglauber:
Sobre o final a esplicação é simples: …
:(

desculpe ai a “esplicação”.

A

Que isso Rafael, já me ajudou muito mesmo, obrigado!

Criado 15 de outubro de 2007
Ultima resposta 18 de out. de 2007
Respostas 11
Participantes 2