2012-12-03 28 views
12

我正在开发这个JPAContainer + Hibernate,并且需要很长时间才能加载。例如,SQLContainer加载60ms的页面和JPA Container加载1.30s的页面。Vaadin JpaContainer

在控制台中使用JPAContainer我看到很多SQL查询 - 对于每个实体 - 查询;实体人员没有指向其他表的链接;

代码jpacontainer:

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

代码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); 

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

我在做什么错?

回答

6

停止对抗JPAContainer,它背后有太多的抽象层。

enter image description here

SQLContainer是不够好,速度快且稳定。我并不是说SQLContainer是JPAContainer的替代品,但实际价格似乎太高。从可用性角度来看,响应速度是一个非常重要的因素,所以最好不要从开始,花在持久层上。

无论如何,有几种可供选择,如果你真的想继续JPAContainer:

使用CachingLocalEntityProvider

经验法则:上网速度慢 - 使用缓存

如果应该减少数据库往返次数, 应该使用CachingLocalEntityProvider。它维护实体和查询结果的本地缓存 ,因此如果数据库往返速度较慢,应该比LocalEntityProvider执行 更快。 但是,它也需要比LocalEntityProvider更多的内存。

使用分页(PagedTable

这将大大降低查询的数量,因为页面延迟加载。

PagedTable是在表现同一事项的 Vaadin核心表,除了它具有多页,而不是 滚动显示多个条目的组件。

enter image description here

使用JPAContainer过滤

所有过滤在与查询数据库级别进行,而不是在容器中。 过滤实现透明地使用JPA 2.0 Criteria API。 由于筛选是在数据库级完成的,因此使用Filterable API的自定义筛选器不起作用。

同时请参阅:JPAContainer Usage and Performance questions

+0

请注意,Vaadin的JPA容器目前有*免费许可证*。 –

1

我的解决方案

在JPAContainerX延长JPAContainer,覆盖getItemIds

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

然后

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非常方便,但有其问题。不仅仅是性能,还有架构问题。除非你依靠它非常好的自动表单生成,否则就忘了它。

我的建议:

  1. 创建其背后隐藏的EntityManager和其他JPA的东西从你的UI代码服务层(EJB,春数据来源,或只是一个自定义辅助类)。
  2. 对于中小型的表格,只需将内容加载到内存中即可。简单且令人惊讶的效率,特别是在内存容量良好的容器中,如来自the Viritin add-on的ListContainer。
  3. 对于内存使用可能会变得很大的真正大型表,使用LazyList助手通过服务层实现延迟加载数据。看看我最近的blog entry about这个话题。