JPA - problemas de paginacao com setMaxResults

0 respostas
diegodrumond
Boa tarde galera... eu estou iniciando agora com JPA a comecei a enfrentar alguns problemas.. possuo uma tabela com uns 30mil registros e preciso ler um a um e fazer algum tipo de processamento... segue abaixo o codigo:
public class ClasseXXX
{
    private static final Logger LOG = Logger.getLogger( "logger" );
    
    private static final Integer FETCH_SIZE = 1000;
    
    private EntityManager em;
    
    public void executar( )
    {
        List<Object> list;
        Query query;
        int i = 0;
        
        list = null;

        LOG.log( Level.INFO, "Inicializando o processamento dos registros..." );
        
        
        while( list == null || list.size( ) > 0 )
        {
            LOG.log( Level.INFO, "Listando os próximos " + FETCH_SIZE + " registros." );

            query = em.createNamedQuery( "ClassePOJO.listar" );
            query.setMaxResults( FETCH_SIZE );
            query.setFirstResult( i * FETCH_SIZE );
            list = query.getResultList( );
            
            LOG.log( Level.INFO, list.size( ) + " registro(s) encontrados." );
            
            for( Object obj : list )
                processaRegistro( obj );
            
            i++;
        }
        
        LOG.log( Level.INFO, "Conversão dos registros executada com sucesso!" );
    }
    
    public EntityManager getEntityManager( )
    { return em; }
    
    public void setEntityManager( EntityManager em )
    { this.em = em; }
    
    public static void main( String[ ] args ) throws Exception
    {
        // Create the EntityManager
        EntityManagerFactory factory = Persistence.createEntityManagerFactory( "cadsus" );
        EntityManager em = factory.createEntityManager( );
        
        ClasseXXX instancia = new ClasseXXX( );
        em.getTransaction( ).begin( );
        instancia.setEntityManager( em );
        instancia.executar( );
        em.getTransaction( ).commit( );
        em.close( );
    }

    private void processaRegistro( Object )
    {
        //processa alguma coisa
    }
    
}
algumas observacoes: 1 - o trecho de codigo
query = em.createNamedQuery( "ClassePOJO.listar" );
            query.setMaxResults( FETCH_SIZE );
            query.setFirstResult( i * FETCH_SIZE );
            list = query.getResultList( );
foi escrito desta forma pois fazendo o createNamedQuery e setMaxResults fora do loop, ele listava todos os registros. pq? sei lah... existe forma de fazer isso? 2 - a transacao foi ativada numa tentativa frustrada de dar em.flush()

Os problemas:

1 - apos processar qse 5 mil registros, ocorre um OutOfMemory... alguem sabe me explicar pq?

2 - a coisa mais bizarra do mundo: algumas vezes o getResultList retorna mais de 1000 registros... o.O
run-single:
[TopLink Info]: 2007.08.07 10:11:24.525--ServerSession(23491286)--TopLink, version: Oracle TopLink Essentials - 2.0 (Build b41-beta2 (03/30/2007))
[TopLink Info]: 2007.08.07 10:11:24.868--Not able to detect platform for vendor name [Firebird]. Defaulting to [oracle.toplink.essentials.platform.database.DatabasePlatform]. The database dialect used may not match with the database you are using. Please explicitly provide a platform using property toplink.platform.class.name.
[TopLink Info]: 2007.08.07 10:11:25.493--ServerSession(23491286)--file:/E:/Projetos/Programa/build/classes/-database login successful
07/08/2007 10:11:25 programa.ClasseXXX executar
INFO: Inicializando a conversão dos registros...
07/08/2007 10:11:25 programa.ClasseXXX executar
INFO: Listando os próximos 1000 registros.
07/08/2007 10:11:58 programa.ClasseXXX executar
INFO: 1200 registro(s) encontrados.
07/08/2007 10:11:58 programa.ClasseXXX executar
INFO: Listando os próximos 1000 registros.
07/08/2007 10:12:30 programa.ClasseXXX executar
INFO: 1000 registro(s) encontrados.
07/08/2007 10:12:31 programa.ClasseXXX executar
INFO: Listando os próximos 1000 registros.
07/08/2007 10:13:08 programa.ClasseXXX executar
INFO: 1200 registro(s) encontrados.
07/08/2007 10:13:09 programa.ClasseXXX executar
INFO: Listando os próximos 1000 registros.
07/08/2007 10:13:33 programa.ClasseXXX executar
INFO: 1000 registro(s) encontrados.
07/08/2007 10:13:40 programa.ClasseXXX executar
INFO: Listando os próximos 1000 registros.
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at org.firebirdsql.gds.XdrInputStream.readSQLData(XdrInputStream.java:89)
[TopLink Info]: 2007.08.07 10:13:57.650--ServerSession(23491286)--file:/E:/Projetos/ADI/ADI_Conversao/CVR_CadSUS/build/classes/-cadsus logout successful
        at org.firebirdsql.jgds.GDS_Impl.isc_dsql_fetch(GDS_Impl.java:1093)
        at org.firebirdsql.jca.FBManagedConnection.fetch(FBManagedConnection.java:828)
        at org.firebirdsql.jdbc.AbstractConnection.fetch(AbstractConnection.java:969)
        at org.firebirdsql.jdbc.FBCachedFetcher.<init>(FBCachedFetcher.java:63)
        at org.firebirdsql.jdbc.FBResultSet.<init>(FBResultSet.java:113)
        at org.firebirdsql.jdbc.AbstractStatement.getCachedResultSet(AbstractStatement.java:568)
        at org.firebirdsql.jdbc.AbstractPreparedStatement.executeQuery(AbstractPreparedStatement.java:115)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:711)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:486)
        at oracle.toplink.essentials.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:437)
        at oracle.toplink.essentials.threetier.ServerSession.executeCall(ServerSession.java:465)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:213)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:199)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:270)
        at oracle.toplink.essentials.internal.queryframework.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:600)
        at oracle.toplink.essentials.internal.queryframework.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2240)
        at oracle.toplink.essentials.internal.queryframework.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2206)
        at oracle.toplink.essentials.queryframework.ReportQuery.executeDatabaseQuery(ReportQuery.java:774)
        at oracle.toplink.essentials.queryframework.DatabaseQuery.execute(DatabaseQuery.java:609)
        at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:677)
        at oracle.toplink.essentials.queryframework.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:731)
        at oracle.toplink.essentials.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2219)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:937)
        at oracle.toplink.essentials.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:909)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:346)
        at oracle.toplink.essentials.internal.ejb.cmp3.base.EJBQueryImpl.getResultList(EJBQueryImpl.java:453)
        at programa.ClasseXXX.executar(ConversaoPessoas.java:98)
        at programa.ClasseXXX.main(ConversaoPessoas.java:139)
Java Result: 1
EXECUTADO COM SUCESSO (tempo total: 2 minutos 43 segundos)

Estou utilizando o netbeans 5.5.1 e o Oracle TopLink Essentials - 2.0 (Build b41-beta2)... estou usando o banco de dados firebird 1.5.4 e o driver jdbc JayBird JCA/JDBC 1.5.5...
Alguem poderia me explicar o pq desses problemas, como corrigir ou se existe alguma outra forma de listar tds os registros de uma tabela sem dar OutOfMemory? Isto é problema da jpa ou do driver JDBC?

vlws...

Criado 7 de agosto de 2007
Respostas 0
Participantes 1