Como lidar com inserts/updates em massa com Hibernate

E ai pessoal,
Recentemente estive procurando saber como otimizar alguns processos com multiplas interações usando o hibernate.
O cenário é de 4000 objetos a serem persistidos.

O script vigente é:


... /** controller ou main **/

try {
					for (PrmParceiro prmP : prmParceiroS) {
						if(prmP.getUsuario()==null){
							prmP.setUsuario(usuario);
						}
						 if (prmP.getId() == null){
							 dao.salvar(prmP);
						 }else{
							 dao.atualizar(prmP);
						 }
					}
				}catch (Exception e) {
					System.out.println("Erro: "+e.getMessage());
					tx.rollback();
				}

...

// metodo salvar e atualizar da dao
...
tx = session.beginTransaction();
session.update(prmP); // ou session.save(prmP)
tx.commit();
...

Percebi que estava iniciando e encerrando a transação (begin, commit) a cada novo laço.
Além de criar vários objetos para transação, a própria transação é uma rotina que exige um x a mais de processamento do servidor sobre a base de dados.
Então criei uma aplicação para testar duas diferentes situações:

  • salvar 4000 objetos com 4000 transações // modelo vigente.
  • salvar 4000 objetos com 1 transação // nova tratativa

... /** controller ou main **/

try {
tx = session.beginTransaction();
					for (PrmParceiro prmP : prmParceiroS) {
						if(prmP.getUsuario()==null){
							prmP.setUsuario(usuario);
						}
						 if (prmP.getId() == null){
							 session.save(prmP);
						 }else{
							 session.update(prmP);
						 }
tx.commit();
					}
				}catch (Exception e) {
					System.out.println("Erro: "+e.getMessage());
					tx.rollback();
				}

...

O correto é não deixar a transação na controller da aplicação, apenas para teste fiz desta forma.
O certo seria ter um método na dao que receba um arraylist para ser persistido ex: salvarParceiroS(ArrayList prmParceciroS) …

O resultado do teste:

A diferença foi de 01:39 mm:ss para 00:02 mm:ss. Em testes locais.
A primeira opção é 46 vezes mais demorada que a segunda.

A pergunta é: Existe alguma outra tratativa que otimize processos de persistencia em massa.

A aplicação de teste está disponível para baixar no endereço http://designcomd.com.br/documents/hibernate.rar
[]s
Jsign.

Para otimização do Hibernate vc pode consultar o manual do hibernate em http://docs.jboss.org/hibernate/core/3.3/reference/en/html/performance.html

Sobre o seu problema: Você ganhou performance fazendo tudo em uma transação, mas se um insert/update der errado vc não terá nenhum dos seus 4000 registros atualizados. Você deve achar um meio termo. Mas informações no manual do hibernate em http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html

Boa noite Graciano,
No manual não temos informações referente a otimização de processos de persistencia em massa, sim, como otimizar consultas usando caches por exemplo.
Gostaria de ter uma opnião real sobre um projeto/processo nestas circunstancias.
Já passou por isso? Como resolveu?

Ter um método que receba um list de objetos a serem persistidos pra você não é uma boa idéia, o que seria melhor?

Sinto muito, mas, quem aceita que meia duzia de objetos pode ser persistidos e o restante não, não me parece uma boa idéia já que está montando um list para isso. Você montaria um list de objetos para serem persistidos se não fosse o caso, onde fica a otimização.

Forcei um pouco na réplica, não me leve a mal, mas parece que respondeu por responder.

[]s
Jsign