Hibernate 瓦丁JPA容器

Hibernate 瓦丁JPA容器,hibernate,vaadin,Hibernate,Vaadin,我正在使用这个JPAContainer+Hibernate,加载它需要很长时间。例如,使用SQLContainer加载60ms的页面和使用JPA容器加载1.30s的相同页面 使用控制台中的JPA容器,我可以看到许多SQL查询——对于每个实体——查询;实体人员没有指向其他表的链接 使用JPA容器进行编码: JPAContainer<Person> container = JPAContainerFactory.make(Person.class, "persis

我正在使用这个JPAContainer+Hibernate,加载它需要很长时间。例如,使用SQLContainer加载60ms的页面和使用JPA容器加载1.30s的相同页面

使用控制台中的JPA容器,我可以看到许多SQL查询——对于每个实体——查询;实体人员没有指向其他表的链接

使用JPA容器进行编码:

JPAContainer<Person> container = JPAContainerFactory.make(Person.class,
            "persistence-unit");
table.setContainerDataSource(container);
My 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>

java:jboss/datasources/mfcfrontendds


我做错了什么?

停止与JPA容器抗争,它背后有太多的抽象层

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

无论如何,如果您确实想继续使用JPA容器,有几个选项可用:

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);
使用CachingLocalEntityProvider

经验法则:访问速度慢--使用缓存

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

使用分页()

这将大大减少查询的数量,因为页面是延迟加载的

PagedTable是一个与 Vaadin核心表,除了它有多个页面而不是 滚动以显示更多条目

使用JPA容器过滤器

@Override
public List<?> getItemIds(int startIndex, int numberOfItems) {
    return doGetEntityProvider().getAllEntityIdentifiers(this,getAppliedFiltersAsConjunction(), getSortByList() ).subList(startIndex, startIndex+numberOfItems);;
}
所有过滤都是在数据库级别通过查询完成的,而不是在容器中。 过滤实现透明地使用JPA2.0标准API。 由于过滤是在数据库级别完成的,因此使用可过滤API的自定义过滤器不起作用

请同时检查:

我的解决方案

在JPAContainerX中扩展JPAContainer,覆盖getItemId

@Override
public List<?> getItemIds(int startIndex, int numberOfItems) {
    return doGetEntityProvider().getAllEntityIdentifiers(this,getAppliedFiltersAsConjunction(), getSortByList() ).subList(startIndex, startIndex+numberOfItems);;
}
@覆盖
公共列表GetItemId(int startIndex,int numberOfItems){
return doGetEntityProvider().getAllEntityIdentifiers(this,GetAppliedFilterSasConnection(),getSortByList()).subList(startIndex,startIndex+numberOfItems);;
}
然后

JPAContainerX容器=新的JPAContainerX(c);
EntityManager EntityManager=JPAContainerFactory.CreateEntityManager持久性单位(IntrastudyUI.PERSISTENCE_单位);
CachingMutableLocalEntityProvider entityProvider=新的CachingMutableLocalEntityProvider(c,entityManager);
container.setEntityProvider(entityProvider);

JPA容器很方便,但也有它的问题。不仅是性能问题,还有架构问题。除非您依赖于它非常好的自动表单生成,否则就别想它了

我的建议是:

  • 创建一个服务层(EJB、Spring数据源,或者仅仅是一个自定义帮助器类),在它后面隐藏EntityManager和其他JPA内容,使其不受UI代码的影响
  • 对于中小型表,只需将内容加载到内存中即可。简单且出人意料的高效,特别是对于一个性能良好的内存容器,如ListContainer from
  • 对于内存使用可能出现问题的非常大的表,请使用LazyList helper通过服务层实现数据的延迟加载。看看我最近关于这个主题的文章

  • 注意,Vaadin的JPA容器目前有一个免费许可证。