Duvida JSF JPA usando Destroy (lentidao)

Boa tarde senhores,

estou com uma duvida aqui… tenho uma aplicação web… em de meus processos necessito deletar uma quantidade aprox 30mil registros
tendo os ids deles em um List.

agora estou fazendo assim…
tenho um for que percorre essa list e chama um metodo destroy passando o id como parametro

assim:

private void removeColeta(List<Integer> idcoletas) {
        for (int id : idcoletas) {
            destroyColeta(id);
        }
    }
    public void destroyColeta(Integer id){
        EntityManager em = null;
        try {
            utx.begin();
            em = getEntityManager();
            Coleta coleta = null;
            try {
                coleta = em.getReference(Coleta.class, id);
                coleta.getIdColeta();
            } catch (EntityNotFoundException enfe) {
                enfe.printStackTrace();
            }
            Fornecedor fornecedorAnt = coleta.getFornecedorAnt();
            if (fornecedorAnt != null) {
                fornecedorAnt.getColetaCollection().remove(coleta);
                fornecedorAnt = em.merge(fornecedorAnt);
            }
            Fornecedor fornecedorAtu = coleta.getFornecedorAtu();
            if (fornecedorAtu != null) {
                fornecedorAtu.getColetaCollection().remove(coleta);
                fornecedorAtu = em.merge(fornecedorAtu);
            }
            Insumo insumoidInsumo = coleta.getInsumoidInsumo();
            if (insumoidInsumo != null) {
                insumoidInsumo.getColetaCollection().remove(coleta);
                insumoidInsumo = em.merge(insumoidInsumo);
            }
            Local localidLocal = coleta.getLocalidLocal();
            if (localidLocal != null) {
                localidLocal.getColetaCollection().remove(coleta);
                localidLocal = em.merge(localidLocal);
            }
            em.remove(coleta);
            utx.commit();
        } catch (Exception ex) {
            try {
                utx.rollback();
            } catch (Exception re) {
                re.printStackTrace();
            }
        } finally {
            if (em != null) {
                em.close();
            }
        }
    }

como sao 30 mil registros a serem deletados… esta muito lento!

esta errado como estou fazendo ? como ou qual a melhor maneira de resolver isso ?

muito obrigado

toda operação solicitada ao banco tem um custo

  1. tempo de envio a operação desejada ao banco
  2. a execução do banco
  3. commit
  4. resposta

isso em algumas operações é tranquilo…

no seu caso é mais crítico, pois ele vai repetir estes passos 30.000 vezes.

Já fiz testes destes nível, usando somente JDBC, boa parte do tempo é consumido somente com a comunicação com o banco.

Use a ferramente profile do netbeans, para saber o ponto que deixa sua aplixação lenta,ela é excelente.

  • Veja seu mapeamento, se for o caso altere para atender o requisito de desempenho;
  • Pesquise sobre como melhorar o desempenho com JPA;
  • Dependendo do caso, se o consumo de tempo for realmente com a comunicação com o banco, tente montar uma string que todos os ids e mande uma só vez para o banco;
  • Veja o Pool de conexão, pode ser tb que sua aplicação esteja criando conexão para cada solicitação;

como eu faria com uma unica String entao ?
ja que tenho todos os ids que necessito deletar.

  1. private void removeColeta(List idcoletas) {
  2.     String query = "DELETE FROM MINHA_TABELA WHERE ID IN (";
         for (int id : idcoletas) {  
    
  3.          query += id + ",";
    
  4.     }
         query = query.substring(0, "".length() - 1) + ")";
    
  5. }

ah…

como sua string vai ficar grande, é melhor usar StringBuffer no lugar de String, pois deve consumir muita memória.

StringBuffer não é necessário, StringBuilder é mais rápido já que não é sincronizado. A propósito, quando se cria uma String utilizando + o compilador já cria um StringBuilder automaticamente, ao contrário do que muitos pensam.

blz,
mas eu fazendo assim…
como ficaria o merge que tenho que dar no fornecedor, insumo e local ?

obg

acho que vc vai ter que tratar isso fora do JPA, somente para estão questão da remoção.

query = query.substring(0, "".length() - 1) + ")"; 

corrigido:
query = query.substring(0, query.length() - 1) + “)”;

Boa tarde amigos
perdao por nao retornar aqui… pois sofri um acidente aí…

entao…

consegui um modo mais facil de resolver isso

com essa query
em.createQuery(“DELETE FROM Coleta AS c WHERE c.coletaAtu IS NULL AND c.coletaAnt IS NULL”).executeUpdate();

eu consigo resolver meu problema…
mas apareceu outro problema… foi atualizado no bando de dados…
porem na memoria nao ! ficou com os dados antigos.

como resolvo isso ? para re sincronizar a minha tabela Coleta ???

obrigado

utiliza cache de 2º nível??

Fernando

Fernando… infelismente nao seu mt sobre jpa…

mas pelo visto deve estar sendo utilizado algum cache sim
pois atualiza no banco e nao na minha app !

abs