2012-12-03 10 views
12

Pracuję nad JPAContainer + Hibernate i ładowanie trwa długo. Na przykład strona z SQLContainer ładuje 60ms i ta sama strona z JPA Container ładuje 1.30s.Vaadin JpaContainer

Z JPAContainer w konsoli widzę wiele zapytań SQL - dla każdej jednostki - zapytanie; Podmiot osoba nie ma linków do innych tabel;

Kod z jpacontainer:

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

Kod z 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); 

Mój plik 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> 

Co robię źle?

Odpowiedz

6

Zatrzymaj walkę z JPAContainerem, za nią jest zbyt wiele warstw abstrakcji.

enter image description here

SQLContainer jest wystarczająco dobry, szybki i stabilny. Nie mówię, że SQLContainer zastępuje JPAContainer, ale rzeczywista cena wydaje się być zbyt wysoka. Z punktu widzenia użyteczności czas reakcji jest bardzo ważnym czynnikiem, więc lepiej nie zaczynać od sekund, wydanej na warstwę trwałości.

W każdym razie, istnieje kilka opcji, jeśli naprawdę chcesz, aby kontynuować JPAContainer:

Używaj CachingLocalEntityProvider

zasada: powolny dostęp - wykorzystanie cache

Jeśli liczba podróży w obie strony powinna zostać zmniejszona, należy zamiast tego użyć CachingLocalEntityProvider. Utrzymuje lokalną pamięć podręczną jednostek i wyników zapytań, a zatem powinna wykonać szybciej niż LocalEntityProvider, jeśli obietnice w obie strony są wolne. Wymaga to jednak również więcej pamięci niż LocalEntityProvider.

Zastosowanie stronicowania (PagedTable)

Będzie ona znacznie zmniejszyć liczbę zapytań, ponieważ strony są leniwi załadowany.

PagedTable jest komponentem, który zachowuje się w tej samej substancji co Vaadin rdzenia tabeli, z wyjątkiem tego, że zawiera wiele stron zamiast przewijania pokazują dodatkowe dane.

enter image description here

Zastosowanie JPAContainer filtruje

Wszystko Filtrowanie odbywa się na poziomie bazy danych z zapytaniami, a nie w pojemniku. Implementacja filtrowania używa przezroczystego interfejsu API JPA 2.0 Criteria. Ponieważ filtrowanie odbywa się na poziomie bazy danych, niestandardowe filtry korzystające z filtrującego interfejsu API nie działają.

Proszę sprawdzić także: JPAContainer Usage and Performance questions

+0

Pamiętaj, że kontener JPA firmy Vaadin ma obecnie * darmową licencję *. –

1

moje rozwiązanie

rozciągają JPAContainer w JPAContainerX, zastępują getItemIds

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

następnie

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 jest przydatny, ale ma swoje problemy. Nie tylko wydajność, ale także problemy z architekturą. Jeśli nie polegasz na całkiem niezłym automatycznym generowaniu formularzy, zapomnij o tym.

Moja sugestia:

  1. Utwórz warstwę usługi (EJB, Spring źródło danych lub tylko niestandardowej klasy pomocnika) za którą ukrycia EntityManager i inne rzeczy WZP z kodu UI.
  2. Dla małych i średnich stołów wystarczy załadować rzeczy do pamięci. Prosta i zaskakująco wydajna, szczególnie z dobrze działającym w pamięci kontenerem, takim jak ListContainer z the Viritin add-on.
  3. W przypadku naprawdę dużych tabel, w których użycie pamięci może stać się problemem, użyj programu LazyList, aby zaimplementować leniwy ładowanie danych za pośrednictwem warstwy usługi. Sprawdź mój ostatni temat: blog entry about.