我很难尝试使用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 。
此时我已经考虑了两种不同的选择:
我没有足够的信心使用第一个解决方案,因为它会涉及一些杂乱的代码来迭代结果并填满实体。
所以我决定试一下第二个选项。我将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。