Carga de dados com Hibernate

4 respostas
mmelgaco

Estou desenvolvendo uma aplicação que irá ler cerca de 50 arquivos todos mês, cada arquivo com cerca de 50000 contas.
Terei de carregar estas contas num banco de dados que servirá de consulta para uma aplicação web.
Fiz um programa em java que lê o arquivo e a medida que vai achando os campos vai setando-os na minha classe hibernate que representa a tabela contas. Para otimizar as pesquisas criei uma tabela de nomes, onde guardo os nomes dos clientes, pois notei que existem muito homônimos, ou seja, muitos nome se repetem.
Aí está meu problema, para carregar corretamente as tabelas, a cada conta que carrego, preciso consultar na tabela de nomes se esse nome já existe. Porém essa consulta está deixando a carga muuuito lenta. Sem a consulta a carga é muito rápida, quando coloco a consulta fica extremamente lenta. Abaixo o meu código, gostaria de uma ajuda no que posso melhorar a velocidade dessa consulta, ou mesmo fazer de outra forma. Muito obrigado!

public class CarregaBanco {

	private static Log log = LogFactory.getLog(CarregaBanco.class);
	
	public boolean InsereContas(ArrayList arrayContas, JProgressBar barraProgressoBanco){

		Transaction tx = null;
		
		try{

			Session sessao = HibernateUtil.currentSession();

			tx = sessao.beginTransaction();
			log.info("Iniciando transacao contas");
			
			for(int i=0;arrayContas.size()>0;i++){
			
				Contas contas = (Contas)arrayContas.remove(0);
				
			        //verificando a existência do nome do cliente
				Query queryNome = sessao.createQuery("from Nomes nomes where nome=:nome");
				queryNome.setString("nome", contas.getNomes().getNome());
				if(queryNome.list().size()>0){
	                contas.setNomes((Nomes)queryNome.list().get(0));
				}else{
			sessao.save(contas.getNomes());
				}
							
                  		sessao.save(contas);
								
				if ( i % 20 == 0 ) { //20, same as the JDBC batch size
					//flush a batch of inserts and release memory:
					sessao.flush();
					sessao.clear();
					//log.info("i="+i);
					barraProgressoBanco.setValue(i);
					  barraProgressoBanco.setString(String.valueOf(i));
				}
				
			}
			log.info("Finalizando transacao contas");
			tx.commit();
			log.info("Transacao contas finalizada!");
			
		}catch(HibernateException e){
			log.error("Exceção hibernate: ", e);
			if(tx!=null){
				try{
					tx.rollback();
				}catch(HibernateException e2){
					log.error("Erro no Roolback", e2);
				}
			}
			return false;
		}
		
		return true;
		
	}
	
}

4 Respostas

_fs

Quantos nomes são? Se não são muitos (centenas de milhares) pode guardá-los numa Collection. Infinitamente mais rápida a consulta.

Rodrigo_Carvalho_Aul

Uma opção feia é fazer uma constraint unique nesse campo no db e tratar a sqlexception.

[]'s

Rodrigo C. A.

mmelgaco

Eu fiz isso, coloquei todos nomes num hashmap.
Mas gastou mais de 1 giga de ram e ainda deu out of memory, pois são quase 4 milhões de nomes. Collection gastaria menos memória ?

T

hashmap e hashsets gastam relativamente bastante memoria (tinha um artigo que mostrava que eles sao viloes para o gc por criarem grande quantidade de objetos)…
as List’s podem gastar menos memoria, mas me parece que o que esta ocupando mais memoria sao os nomes mesmo…
alem disso, buscas em lists precisam percorrer o array inteiro (ou fazer sort a quase todo momento), o que tornara o processo lento…
a saida de marcar o campo como unique e tratar a excecao funciona, embora seja um tanto deselegante (nada pessoal rodrigo)…

Criado 20 de abril de 2006
Ultima resposta 20 de abr. de 2006
Respostas 4
Participantes 4