2012-12-03 21 views
12

Sto lavorando a questo JPAContainer + Hibernate e richiede molto tempo per il caricamento. Ad esempio pagina con SQLContainer che carica 60 ms e stessa pagina con contenitore JPA che carica 1.30s.Vaadin JpaContainer

Con JPAContainer in console vedo molte query SQL - per ogni entità - query; Entity Person non ha collegamenti ad altre tabelle;

Codice con jpacontainer:

JPAContainer<Person> container = JPAContainerFactory.make(Person.class, 
      "persistence-unit"); 
table.setContainerDataSource(container); 

Codice con SQLContainer:

JDBCConnectionPool pool = null; 
    try { 
     pool = new SimpleJDBCConnectionPool("org.postgresql.Driver", 
       "jdbc:postgresql://127.0.0.1:5432/postgres", "postgres", 
       "pwd"); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
    TableQuery tq = new TableQuery("Person", pool); 
    SQLContainer sqlContainer = null; 
    try { 
     sqlContainer = new SQLContainer(tq); 
    } catch (SQLException e) { 
     e.printStackTrace(); 
    } 
table.setContainerDataSource(sqlContainer); 

mio file persistence.xml:

<persistence-unit name="persistence-unit" transaction-type="RESOURCE_LOCAL"> 

    <jta-data-source>java:jboss/datasources/mfc-frontendDS</jta-data-source> 

    <properties> 
    <!-- Properties for Hibernate --> 
    <property name="hibernate.archive.autodetection" value="class"/> 
    <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> 
    <property name="hibernate.show_sql" value="true"/> 
    <property name="hibernate.format_sql" value="true"/> 
    <property name="hibernate.use_sql_comments" value="true"/> 
    <property name="hibernate.hbm2ddl.auto" value="update"/> 
    <property name="hibernate.temp.use_jdbc_metadata_defaults" value="false"/> 
    <property name="hibernate.transaction.jta.platform" value="org.hibernate.service.jta.platform.internal.JBossAppServerJtaPlatform" /> 
    </properties> 

Che cosa sto facendo di sbagliato?

risposta

6

Stop alla lotta con JPAContainer, ci sono troppi livelli di astrazione dietro di esso.

enter image description here

SQLContainer è abbastanza buono, veloce e stabile. Non sto dicendo che SQLContainer è un sostituto di JPAContainer, ma il prezzo effettivo sembra essere troppo alto. Dal punto di vista dell'usabilità, la reattività è un fattore molto importante, quindi è meglio non iniziare con secondi, speso sul livello di persistenza.

In ogni caso, ci sono diverse opzioni disponibili, se si vuole veramente di continuare con JPAContainer:

Usa CachingLocalEntityProvider

Regola generale: accesso lento - l'uso della cache

Se il il numero di viaggi di andata e ritorno del database dovrebbe essere ridotto, si consiglia di utilizzare CachingLocalEntityProvider. Mantiene una cache locale di di entità e risultati di query e quindi dovrebbe eseguire più veloce di LocalEntityProvider se i round trip del database sono lenti. Tuttavia, richiede anche più memoria di LocalEntityProvider.

Usa paginazione (PagedTable)

si ridurrà notevolmente il numero di query, perché le pagine sono pigri caricato.

PagedTable è un componente che si comporta nello stesso materia come Tabella nucleo Vaadin, tranne che ha più pagine anziché scorrimento per mostrare più voci.

enter image description here

Usa JPAContainer filtri

Tutto il filtraggio avviene a livello di database con le query, non nel contenitore. L'implementazione filtraggio utilizza il Criteria API JPA 2.0 trasparente. Come il filtraggio è fatto a livello di database, filtri personalizzati che utilizzano l'API filtrabili non funzionano.

prega di controllare anche: JPAContainer Usage and Performance questions

+0

Si noti che il contenitore di APP Vaadin ha attualmente una licenza * gratis *. –

1

mia soluzione

estendere JPAContainer in JPAContainerX, ignorare getItemIds

@Override 
public List<?> getItemIds(int startIndex, int numberOfItems) { 
    return doGetEntityProvider().getAllEntityIdentifiers(this,getAppliedFiltersAsConjunction(), getSortByList()).subList(startIndex, startIndex+numberOfItems);; 
} 

poi

JPAContainerX<T> container = new JPAContainerX<T>(c); 

    EntityManager entityManager = JPAContainerFactory.createEntityManagerForPersistenceUnit(IntrastudyUI.PERSISTENCE_UNIT); 

    CachingMutableLocalEntityProvider<T> entityProvider = new CachingMutableLocalEntityProvider<T>(c , entityManager); 

    container.setEntityProvider(entityProvider); 
0

JPAContainer è utile ma presenta problemi. Non solo prestazioni, ma anche problemi architettonici. A meno che tu non dipenda dalla sua generazione di moduli automatica piuttosto carina, dimenticala.

Il mio suggerimento:

  1. creare un livello di servizio (EJB, fonte dei dati Primavera, o semplicemente una classe di supporto personalizzato) dietro la quale si nasconde EntityManager e altre cose JPA dal codice utente.
  2. Per piccole e medie dimensioni le tabelle, basta caricare la roba in memoria. Semplice e sorprendentemente efficiente, soprattutto con un funzionamento soddisfacente nel contenitore memoria come ListContainer da the Viritin add-on.
  3. Per davvero grandi tavoli in cui l'utilizzo di memoria può diventare problema, utilizzare lazylist aiutante di implementare lazy loading dei dati tramite il vostro livello di servizio. Controlla il mio recente blog entry about l'oggetto.