Ola todos,
É o seguinte: Eu tenho um programa que lê uma tabela DBF e o codigo abaixo que grava num banco MySQL. O problema que ate os 1500 registros é super rápido, depois fica lento demais. Gostaria de saber se há algo que possa ser melhorado no codigo para que a performance seja sempre alta. Desde já agradeco.
public void inserirVenda(Collection<Movcaixa> vendas) {
EntityManager em = getEntityManager();
EntityTransaction et = em.getTransaction();
for (Movcaixa venda : vendas) {
Venda v = new Venda(venda.getCdprod(), venda.getLoja(), venda.getPrecounit(), venda.getQuant(), venda.getData());
try {
et.begin();
em.persist(v);
et.commit();
} catch (Exception ex) {
System.out.println(ex.getLocalizedMessage());
try {
et.rollback();
} catch (Exception ex1) {
System.out.println(ex1.getLocalizedMessage());
}
}
}
em.close();
}
Pelo que eu entendi, você passa uma coleção de vendas e quer persistir essas vendas no banco. Certo?
No meu caso, eu faria da seguinte forma: uma entidade (no caso, uma tabela) X que teria uma lista de vendas (Set) e usaria Cascade.ALL (ou Cascade.PERSIST, vai depender do que você quer). Assim, você não precisa desse for, só de um persist(X), que iria persistir as Movcaixa nas suas tabelas.
Algo assim:
@Entity
public class X {
// ...
@OneToMany(mappedBy = "qualquercoisa", cascade = CascadeType.PERSIST)
private Set<Venda> vendas;
}
@Entity
public class Venda {
// ...
}
ps.: seria interessante dar um nome melhor a Movcaixa.
ps2.: marlls, usar ASP.NET com o MVC.NET framework é ótimo (é verdade mesmo, não é sarcasmo. Gostei muito de trabalhar com o framework e com a tecnologia). Mas no caso dele, é em Java. O “por que não usar” é complexo quando existem coisas prontas e existem restrições de orçamento, pessoal e tempo.
Vale ressaltar que os códigos são meramente exemplos (e bem toscos e incompletos).
eu te sugeriria para ao invéz de abrir uma transação pra cada objeto persistido e dar o commit, abrir uma transação, persistir uns 50 ou 100 objetos e só depois disso dar o commit… desse jeito vc fica abrindo e fechando transação toda hora… ve se assim resolve alguma coisa.
marlls isso não é feito por um simples motivo, ele ja esta com a aplicação rodando em java, provavelmente precisando apenas de certos ajustes, como foi dito, nessa parte relativa a persistencia, não há motivo para recomeçar tudo do zero. O motivo para não usar asp.net MVC é por que a aplicação só esta com este problema nessa parte relativa a persistencia, e que provavelmente nem é problema da tecnologia que ele está usando, ou seja, não existe motivo para recomeçar tudo do zero… mudar de linguagem, de plataforma, logo de framework MVC (o amigo nem citou se esta utilizando algum até por que isso não tem nenhuma relação com o problema) e inclusive mudar de banco de dados (aliais de um free para outro muito bem pago por sinal…).
não to dizendo que a tecnologia que você citou seja necessariamente pior para resolver esse problema, o linq facilita um bocado, mais em java também tem um monte de tecnologias que “funcionam tri bem” da mesma forma… (de modo que essa tecnologia que você falou também não é necessariamente superior, cada caso é um caso).
bom… espero ter respondido sem ser de forma ofensiva como você estava esperando, mais assim mesmo sua resposta foi totalmente incondizente com o problema…
Pelo que eu entendi é processamento batch, então eu iria pelo caminho de usar session stateless.
tem um capítulo na documentação do hibernate que fala sobre como ter bom desempenho nesses casos.
[quote=thimor]Ola todos,
É o seguinte: Eu tenho um programa que lê uma tabela DBF e o codigo abaixo que grava num banco MySQL. O problema que ate os 1500 registros é super rápido, depois fica lento demais. Gostaria de saber se há algo que possa ser melhorado no codigo para que a performance seja sempre alta. Desde já agradeco.
[/quote]
A solução é paralarizar o seu for. Utiliza mais do que uma thread para processar a lista. Utilize o padrão Produtor-Consumidor.
Para a implementação utilize Executor do java 6. Ou pode fazer na mão se vc é bom de threads.
A transação não precisa englobar todas as threads. E tem que ter cuidado com as exceções.
Para maior controle use UnitOfWork. Separe a lista mãe em listas menores. Se algum item der erro, mova-o para outra lista.
Acumle todos os que deram erro e tente de novo esses. Os que não passarem da segunda vez, registre isso num log e descarte.
Muito obrigado pelas respostas. marlls1989 vc nao vai apanhar, como os amigos disseram o programa ja ta rodando trocar a tecnologia nao é viavel. Andre Brito vou testar sua solucao, obrigado. maior_abandonado tentei fazer desse jeito deu OutOfMemory. ViniGodoy, nao fiz profile. thiagoks vou dar uma olhada na documentacao do hibernate, to usando toplink. sergiotaborda obrigado parece ser uma solucao bem mais interessante, vou testar dessa forma.
Obrigado a todos pela solucao.
Eu pensei em fazer tb par resolver esse problema gerar um arquivo de insert pelo clipper e ver se o ms sqlserver tem alguma procedimento automatico de importacao no DTS para todos os dias ler o arquivo gerado e adicionar na tabela. Talvez essa seja a forma mais rapida.