将 SQL 查询数据映射回存储库中的 Java 对象

Map SQL query data back into Java Object in Repository

我开始使用 Hibernate 进行查询,我注意到如果我想使用存储库来执行查询,我必须使用存储库中的实体来映射 returned 数据库的值。

我是否可以在任何存储库中 运行 查询和 return 数据并映射到具有相同名称的 java class。

喜欢

@Query(value = "SELECT location_id, (3959 * acos (cos(radians(:lat)) * cos(radians(l.latitude)) * cos(radians(l.longitude) - radians(:lon))  + sin(radians(:lat)) * sin(radians(l.latitude)))) AS distance FROM location l having distance < :mile order by distance limit 0, :limitNum", nativeQuery = true)
List<LocationDistance> searchLocationByRadius(@Param("lat") double lat, @Param("lon") double lon, @Param("mile") double distance, @Param("limitNum") int limit);

因此从 Query 编辑的 location_id 和距离字段 return 将自动映射到 LocationDistance 对象。

您有 2 个选择:

  1. 切换到 JPQL 查询并在查询中使用构造函数,例如:
@Query(value = "SELECT new example.LocationDistance(location_id, distance_calculation) " +
               "FROM location ...")
List<LocationDistance> searchLocationByRadius(@Param("lat") double lat, @Param("lon") double lon, @Param("mile") double distance, @Param("limitNum") int limit); 

在这种方法中,您不能直接使用 cos/sin/radians 函数,因为 JPQL 不支持它们。相反,您需要使用 JPQL function 来调用它们,例如:

function('cos', tab.column)

或者如果你使用休眠,你可以register a function with a hibernate dialect

  1. 切换到 @SqlResultSetMapping@NamedNativeQuery

首先,您需要添加 @SqlResultSetMapping@NamedNativeQuery 注释 到您的实体 class.

@SqlResultSetMapping(
           name="myMapping",
           classes={
              @ConstructorResult(
                   targetClass=LocationDistance.class,
                     columns={
                        @ColumnResult(name="location_id"),
                        @ColumnResult(name="distance")
                        }
              )
           }
)
@NamedNativeQuery(name="Location.searchLocationByRadius", 
        resultSetMapping="myMapping", 
        query="...")
@Entity
public class Location {
  ...
}

其次,您需要向您的 spring 存储库接口添加一个方法,该方法的名称与您的 @NamedNativeQuery.

的名称完全相同
@Repository
public interface LocationRepository extends JpaRepository<Location, Long> {
    List<LocationDistance> searchLocationByRadius(...);
}