在EclipseLink上解析JPQL时出错(Hermes Parser)

时间:2017-07-20 18:03:40

标签: postgresql eclipselink jpql

我很难尝试使用JPQL解决问题。 我正在努力解决系统上的一些性能问题,而且我没有太多空间来改变项目的结构(数据库表和/或实体)。

代码上存在选择N + 1的问题,因为此系统正在广泛使用本机查询。所以我决定挑选最糟糕的查询并尝试将它们转换为JPQL。

我不确定这是否是上述情况的最佳解决方案。

原始原生查询:

SELECT is.*
FROM (SELECT id_map, id_spot, 
      json_array_elements(id_itineraries)::text::integer AS itinerary
      FROM itinerary_spot WHERE id_map=?) tmp
JOIN itinerary_spot is ON tmp.id_spot=is.id_spot AND tmp.id_map=is.id_map 
WHERE tmp.itinerary=?

此查询工作正常,但它没有使用实体Spot进行JOIN以避免选择N + 1

此时我已经考虑了两种不同的选择:

  1. 改进本机SQL查询,将JOIN添加到Spot表,然后使用@SqlResultSetMapping填充实体(行程和Spot)。
  2. 将查询转换为JPQL,让EclipseLink 2.6发挥其神奇作用。
  3. 我没有足够的信心使用第一个解决方案,因为它会涉及一些杂乱的代码来迭代结果并填满实体。

    所以我决定试一下第二个选项。我将Native查询转换为 完整查询:

    SELECT is FROM ItinerarySpot is, 
                    (SELECT cs.itinerarySpotPK.idMap, 
                            cs.itinerarySpotPK.idSpot, 
                            SQL('json_array_elements(id_itineraries)::text::integer') AS itinerary 
                     FROM ItinerarySpot cs
                     WHERE cs.itinerarySpotPK.idMap = :idMap
                    ) x
    WHERE x.idSpot = is.itinerarySpotPK.idSpot
      AND x.idMap = is.itinerarySpotPK.idMap
      AND x.itinerary = :idItinerary
    
    List<ItinerarySpot> fullJPQLResult = baseDAO.runQuery( ItinerarySpot.class, fullJPQL, params );
    

    问题是,我从EclipseLink(HermesParser)收到的错误并没有帮助我找出我的JPQL有什么问题:

    Exception Message:
    An exception occurred while creating a query in EntityManager: Exception Description: Internal problem encountered while compiling [<my-query-above>]. Internal Exception: java.lang.NullPointerException
    
    Exception Stacktrace: 
    [org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1616), 
            org.eclipse.persistence.internal.jpa.EntityManagerImpl.createQuery(EntityManagerImpl.java:1636), 
            com.mycompany.dao.BaseDAO.runQuery(BaseDAO.java:781), 
            com.mycompany.bo.impl.retail.ItinerarySpotBO.findItinerarySpots(ItinerarySpotBO.java:357), 
            com.mycompany.bo.impl.retail.ItineraryBO.buildItineraryFull(ItineraryBO.java:316), 
            com.mycompany.bo.impl.retail.ItineraryBO.buildItineraryStatus(ItineraryBO.java:366), 
            com.mycompany.bo.impl.retail.ItineraryBO.listItineraries(ItineraryBO.java:518), 
            com.mycompany.bo.impl.retail.SpotBO.buildSpotActivities(SpotBO.java:520), 
            com.mycompany.bo.impl.retail.SpotBO.buildSpotActivities(SpotBO.java:473), 
            com.mycompany.action.retail.ActivityAction.recommendedActivities(ActivityAction.java:149), 
            sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method), 
            sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57), 
            sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43), 
            java.lang.reflect.Method.invoke(Method.java:606), 
            com.mycompany.service.ActionInvoker.invokeAction(ActionInvoker.java:128), 
            com.mycompany.service.JSONService.service(JSONService.java:101), 
            javax.servlet.http.HttpServlet.service(HttpServlet.java:729), 
                    ...
                    ...
            java.lang.Thread.run(Thread.java:745)]
    

    当我从完整的JPQL中删除&#39; AND x.itinerary =:idItinerary&#39; 时(它会编译并执行)。

    欢迎任何帮助确定问题。我也开放尝试另一种方法来解决选择N + 1。

0 个答案:

没有答案