JPA:如何将@NamedStoredProcedureQuery 与@NamedQuery 结合起来执行周边搜索?

Posted

技术标签:

【中文标题】JPA:如何将@NamedStoredProcedureQuery 与@NamedQuery 结合起来执行周边搜索?【英文标题】:JPA: How to combine a @NamedStoredProcedureQuery with a @NamedQuery to perform a perimeter search? 【发布时间】:2014-07-22 11:49:41 【问题描述】:

我有一些实体 BC 从父实体 A 继承。因此,我的数据库中有一个连接的多重继承结构。 此外,我在这些实体上定义了一些@NamedQueries,它们运行良好。 我打算有一个 @NamedStoredProcedureQuery 能够在外围找到一些 POI。我已经实现了一个存储过程,它在父表上执行 SELECT,获取 longitude,latituderadius 作为参数,并且 CALL 返回正确的记录。执行边界搜索的列都在父表/实体中。

现在我想使用与继承实体相关的 JPA 从 Java 调用此存储过程。这意味着对 B 类实体的周界搜索应返回周界内所有 B 类的 POI。

在父实体类中定义 @NamedStoredProcedureQuery 是否足够? 如何在子类的 @NamedQuery 中调用这样的 @NamedStoredProcedureQuery

【问题讨论】:

JPQL 查询不能调用存储过程,因此 NamedQuery 不能调用 NamedStoredProcedureQuery。您使用 JPA API 自己调用它们 您使用哪种 JPA 实现? 【参考方案1】:

我创建了一个存储过程,其中包含必要的 IN 参数以及要使用的表的进一步 IN 参数。

DELIMITER $$
CREATE PROCEDURE `perimeterSearch`(IN lon double, IN lat double, IN radius double, 
                                IN poiTable varchar(45))
BEGIN
SET @perimeterSearch = CONCAT(
'SELECT
   -- poiId,
   -- latitude,
   -- longitude,
    *
FROM
    ', 'mySchema.', poiTable, ' pt ', 

' 
LEFT JOIN mySchema.pois p ON p.poiId = pt.poiId 
HAVING
    -- distance <= radius
(
        6371 * acos(
            cos(
                radians( p.latitude )
            ) * cos(
                radians( ', lat, ' ) 
            ) * cos(
                radians( p.longitude ) - radians( ', lon, ' ) 
            ) + sin(
                radians( ', lat, ' ) 
            ) * sin(
                radians( p.latitude )
            )
        )
    ) <= ', radius, ' 
');
-- ORDER BY
--    distance ASC;
PREPARE stmt FROM @perimeterSearch;
EXECUTE stmt;
END

在我的 DAO 实现中我执行

public List<MyPoiPoiEntity> findMyPoisInPerimeter(final double longitude, final double latitude, final double radius)
        em = factory.createEntityManager();
        final StoredProcedureQuery ppQuery =
                em.createStoredProcedureQuery("perimeterSearch", MyPoiEntity.class) 
                .registerStoredProcedureParameter("longitude", double.class, ParameterMode.IN)
                .setParameter("longitude", longitude)
                .registerStoredProcedureParameter("latitude", double.class, ParameterMode.IN)
                .setParameter("latitude", latitude)
                .registerStoredProcedureParameter("radius", double.class, ParameterMode.IN)
                .setParameter("radius", radius)
                .registerStoredProcedureParameter("poiTable", String.class, ParameterMode.IN)
                .setParameter("poiTable", MyPoiEntity.class.getAnnotation(Table.class).name());
        final List<MyPoiEntity> cpEntities = ppQuery.getResultList();
        em.close();
        return cpEntities;      
    

使用正确表格的技巧是由

完成的
.setParameter("poiTable", MyPoiEntity.class.getAnnotation(Table.class).name());

这样我可以确定正确的实体表与使用字符串文字相反。

【讨论】:

以上是关于JPA:如何将@NamedStoredProcedureQuery 与@NamedQuery 结合起来执行周边搜索?的主要内容,如果未能解决你的问题,请参考以下文章

JPA:如何将原生查询结果集转换为 POJO 类集合

如何将 JPA 添加到现有的 Eclipse 项目?

如何将 JPA 调整为 Criteriaquery

如何将@UniqueConstraint 与单表继承(JPA)一起使用?

如何将 LocalDateTime 提供给 jpa/hibernate 查询?

如何将嵌套列表的列表传递到 JPA 本机查询中