Como transmitir os resultados de Hibernate / JPA e os recursos da versão, dado processado?

bebida:

Eu estou usando dados Spring, JPA e Hibernate para executar uma função em cada maior registro de um determinado ID.

Aqui é o meu DAO:

public interface MyEntityDao extends JpaRepository<MyEntity, Long>, {

    @QueryHints(value = @QueryHint(name = org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE, value = "1000"))
    Stream<MyEntity> findByIdGreaterThanOrderByIdAsc(Long id);
}

O método é usado como este, e ele funciona:

@Transactional(readOnly = true)
public void printRecordsGreaterThan(Long lastId) {
    myEntityDao.findByIdGreaterThanOrderByIdAsc(lastId).forEach((entity) -> {
        System.out.println("entity: " entity.getId());
    });
}

A questão é quando esta operação tem de digitalizar uma gama muito grande. I monitorado com VisualVM e está mantendo todos os registros na memória (Dezenas de pena GB de RAM).

Existe alguma maneira de ter este código liberar os recursos, uma vez que são processados ​​em vez de mantê-los na memória?

Desde já, obrigado!

Solução

Graças a @julodnik nos comentários, invocando clear()sobre o gerenciador de entidades de vez em quando resolveu o problema.

@PersistenceContext
private EntityManager em;

@Transactional(readOnly = true)
public void printRecordsGreaterThan(Long lastId) {
    AtomicLong counter = new AtomicLong();
    myEntityDao.findByIdGreaterThanOrderByIdAsc(lastId).forEach((entity) -> {
        long count = counter.getAndIncrement();
        if (count % 1000 == 0) {
            logger.info(String.format("Clearing %s session for result %d",  type.toString(), counter.get()));   
            em.clear();
        }
        System.out.println("entity: " entity.getId());
    });
}
julodnik:

Você pode usar setFirstResult e setMaxResults para iterar sobre um grande conjunto de resultados. Você pode encontrar um exemplo nesta questão relacionada .

Outra questão que vem à minha mente é que você pode ter ansiosos fetch definida por padrão. Isto significa que você pode estar recebendo todas as entidades relacionadas e se eles têm entidades relacionadas serão buscados também. Você deve ligar as instruções SQL em seu arquivo de log para verificar se isso está acontecendo.

--- EDIT para responder a comentário

Se os objetos não estão sendo referenciado em java, então você pode limpar o primeiro cache de nível com flush e limpar (em entitymanager). Isso deve limpar todos os objetos carregados.

Acho que você gosta

Origin http://43.154.161.224:23101/article/api/json?id=331695&siteId=1
Recomendado
Clasificación