12

I'm working this JPAContainer + Hibernate and it takes a long time to load. For example page with SQLContainer loading 60ms and same page with JPA Container loading 1.30s.

With JPAContainer in console I see many SQL queries - for each entity - query; Entity Person does not have links to other tables;

Code with jpacontainer:

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

Code with 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);

My persistence.xml file:

<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>

What am I doing wrong?

Johan
  • 74,508
  • 24
  • 191
  • 319
Alexey Smirnov
  • 133
  • 1
  • 6

3 Answers3

6

Stop fighting JPAContainer, there are too many abstraction layers behind it.

enter image description here

SQLContainer is good enough, fast and stable. I'm not saying SQLContainer is a replacement for JPAContainer, but the actual price seems to be too high. From the usability perspective responsiveness is a very important factor, so it is better not to start with seconds, spent on persistence layer.

Anyway, there are several options available if you really want to continue with JPAContainer:

Use CachingLocalEntityProvider

Rule of thumb: slow access -- use cache

If the number of database round-trips should be reduced, CachingLocalEntityProvider should be used instead. It maintains a local cache of entities and query results and hence should perform faster than LocalEntityProvider if database round-trips are slow. However, it also requires more memory than LocalEntityProvider.

Use paging (PagedTable)

It will greatly reduce number of queries, because pages are lazy loaded.

PagedTable is a component that behaves in the same matter as the Vaadin core Table, except that it has multiple pages instead of scrolling to show more entries.

enter image description here

Use JPAContainer filters

All filtering is done at the database level with queries, not in the container. The filtering implementation uses the JPA 2.0 Criteria API transparently. As the filtering is done at the database-level, custom filters that use the Filterable API do not work.

Please also check: JPAContainer Usage and Performance questions

Renat Gilmanov
  • 17,735
  • 5
  • 39
  • 56
1

my solution

extend JPAContainer in JPAContainerX, override getItemIds

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

then

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);
Mauro Braggio
  • 326
  • 3
  • 7
0

JPAContainer is handy but has its issues. Not just performance, but architectural problems as well. Unless you depend on its pretty nice automatic form generation, just forget about it.

My suggestion:

  1. Create a service layer (EJB, Spring Data source, or just a custom helper class) behind which you hide EntityManager and other JPA stuff from your UI code.
  2. For small to medium sized tables, just load the stuff into memory. Simple and surprisingly efficient, especially with a well performing in memory Container like ListContainer from the Viritin add-on.
  3. For really large tables where memory usage may become issue, use LazyList helper to implement lazy loading of data via your service layer. Check out my recent blog entry about the subject.
user229044
  • 232,980
  • 40
  • 330
  • 338
mstahv
  • 1,784
  • 9
  • 7