2012-11-27 9 views
2

我是JPA的新手,我为我的web服务编写了简单的JPA选择。我以前使用 经典SQL语句。这很棒,我知道如何获得稳定的速度,但我现在正在5个不同的项目中使用3个不同的数据库。所以我认为学习JPA是使用一种技术的好方法,而不必知道3种SQL语言。所以我创建了一些表格,实体并试图使用JPA。但是第一时间有些问题 - 速度。JPA select为db创建了很多请求,性能

(我使用的是MSSQL 2008)

我比较简单的本地SQL选择和JPA选择:

em.createNativeQuery("SELECT c.* FROM Table c", MyTable.class); 

em.createQuery("SELECT c FROM Table c", MyTable.class) 

createNativeQuery是5倍快,但为什么呢?

因此,我启动了包含在MSSQL包中的SQL分析器,并调试了JPA正在做的事情。 我有100条记录的表,什么我看到让我大吃一惊:

  • createNativeQuery创建1个请求DB和结果查询100条记录
  • createQuery创建100个请求,每个请求返回1项纪录。事情是这样的:

    1 SELECT Col1, Col2 FROM TABLE WHERE (ID = ?)<br> 
    2 SELECT Col1, Col2 FROM TABLE WHERE (ID = ?)<br> 
    . 
    . 
    . 
    100 SELECT Col1, Col2 FROM TABLE WHERE (ID = ?) 
    

我使用JPA 2与Eclipse链接。这是JPA如何工作的正常行为?或者我在我的设置中做错了什么。

+0

你使用* load()*方法来获取数据? –

+0

您还没有提到这些查询发生的时间。我建议转换EclipseLink日志记录来查看它发布的SQL和时间,如下所述:http://wiki.eclipse.org/EclipseLink/Examples/JPA/Logging并尝试确定何时发布这些选择。我敢打赌,你的应用程序在迭代结果时访问了一些懒惰属性,从而导致获取组被一个接一个地触发。在这里描述访存组:http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Advanced_JPA_Development/Performance/Fetch_Groups检查col1 + col2的映射 – Chris

回答

1

这样做是为了优化您不需要一次使用所有结果对象的情况。 EclipseLink首先加载对象骨架,并在遍历对象时将它们填充到场景后面。

如果要加载一次的所有对象,然后我觉得QueryHint下面应该有所帮助:

Query query = em.createQuery("SELECT c FROM Table c", MyTable.class) 
    query.setHint(QueryHints.BATCH_SIZE, 100); //set any appropriate batch size 
0

你不应该使用createNativeQuery一个简单的例子,你已经提供。

尝试这样的事情(使用Query代替):

Query agedUsers = em.createQuery("SELECT u " + "FROM Users u " 
      + "WHERE u.age = :age"); 
    agedUsers.setParameter("age", age); 
    List<User> users = agedUsers.getResultList(); 

表名是实体的名称,您必须使用别名来代替*

0

对不起,我让jpa使用逐行加载和使用QueryHints.BATCH_SIZE时有点乱。 你能解释我何时创建骨架以及何时填充数据?
当我将数据返回列表时:

List users = agedUsers.getResultList();

我有列表映射到primefaces数据表,当dataTable呈现时,或当查询返回 列表时填充数据?

何时使用让jpa逐行加载数据,何时使用QueryHints.BATCH_SIZE更好地加载数据?