PSQLException:在此 ResultSet 中找不到列名 clazz_

Posted

技术标签:

【中文标题】PSQLException:在此 ResultSet 中找不到列名 clazz_【英文标题】:PSQLException: The column name clazz_ was not found in this ResultSet 【发布时间】:2018-09-23 01:11:18 【问题描述】:

我正在尝试获取PlaceEntity。我之前存储了一堆GooglePlaceEntity 对象,其中

@Entity
@Table(name = "place")
@Inheritance(
        strategy = InheritanceType.JOINED
)
public class PlaceEntity extends AbstractTimestampEntity 

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

@Entity
@Table(name = "google_place")
public class GooglePlaceEntity extends PlaceEntity 
    // Additional fields ..


但是,我既不想发送存储在google_place 中的信息,也不想不必要地加载它。出于这个原因,我只是在获取

public interface PlaceRepository extends JpaRepository<PlaceEntity, Long> 

    @Query(value = "" +
            "SELECT * " +
            "FROM place " +
            "WHERE earth_distance( " +
            "   ll_to_earth(place.latitude, place.longitude), " +
            "   ll_to_earth(:latitude, :longitude) " + 
            ") < :radius",
            nativeQuery = true)
    List<PlaceEntity> findNearby(@Param("latitude") Float latitude,
                                 @Param("longitude") Float longitude,
                                 @Param("radius") Integer radius);


我得到的是这样的:

org.postgresql.util.PSQLException: The column name clazz_ was not found in this ResultSet.
    at org.postgresql.jdbc.PgResultSet.findColumn(PgResultSet.java:2588) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
    at org.postgresql.jdbc.PgResultSet.getInt(PgResultSet.java:2481) ~[postgresql-9.4.1208-jdbc42-atlassian-hosted.jar:9.4.1208]
    at com.zaxxer.hikari.pool.HikariProxyResultSet.getInt(HikariProxyResultSet.java) ~[HikariCP-2.7.8.jar:na]
    at org.hibernate.type.descriptor.sql.IntegerTypeDescriptor$2.doExtract(IntegerTypeDescriptor.java:62) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    at org.hibernate.type.descriptor.sql.BasicExtractor.extract(BasicExtractor.java:47) ~[hibernate-core-5.2.14.Final.jar:5.2.14.Final]
    ...

我可以在纯 PostgreSQL 中运行这条语句:

SELECT * FROM place WHERE 
earth_distance( 
  ll_to_earth(place.latitude, place.longitude), 
  ll_to_earth(17.2592522, 25.0632745)
) < 1500;

但不使用JpaRepository

顺便说一句,获取GooglePlaceEntity 是有效的:

@Query(value = "" +
        "SELECT * " +
        "FROM place JOIN google_place ON google_place.id = place.id " +
        "WHERE earth_distance( " +
        "   ll_to_earth(place.latitude, place.longitude), " +
        "   ll_to_earth(:latitude, :longitude) " + 
        ") < :radius",
        nativeQuery = true)
List<GooglePlaceEntity> findNearby(@Param("latitude") Float latitude,
                                   @Param("longitude") Float longitude,
                                   @Param("radius") Integer radius);

【问题讨论】:

已删除答案,找到一个完全相同的答案***.com/questions/2140992/… @Zeromus 我很想听听这背后的技术故事。我调试了代码,它似乎在检测到一个类已经派生时分支,然后它尝试构建这样一个连接查询,至少在我看来,它不应该这样做。但是,编写本机查询并不是我使用 Hibernate 的原因。此时我将 is-a 转换为 has-a 关系。 【参考方案1】:

如果是@Inheritance(strategy = InheritanceType.JOINED),当您在JPA 存储库 中检索没有nativeQuery=True 的数据时,Hibernate 将执行如下SQL:

SELECT
table0_.id as id1_1_,
table0_.column2 as column2_2_1_,
... (main_table cols)
table0_1_.column1 as column1_1_0_,
... (table1 to N-1 cols)
table0_N_.column1 as column1_1_9_,
... (tableN-th cols)
CASE WHEN table0_1_.id is not null then 1
    ... (table1 to N-1 cols)
    WHEN table0_N_.id is not null then N
    WHEN table0_.id is not null then 0
    END as clazz_
FROM table table0_
left outer join table1 table0_1_ on table0_.id=table0_1_.id
... (other tables join)
left outer join table2 table0_N_ on table0_.id=table0_N_.id

从上面的 SQL 可以看到 clazz 规范。如果您想将 ResultSet 映射到您的超级实例(PlaceEntity),您应该自己在 SELECT 中指定 clazz_ 列。

你的情况是:

@Query(value = "" +
            "SELECT *, 0 AS clazz_ " +
            "FROM place " +
            "WHERE earth_distance( " +
            "   ll_to_earth(place.latitude, place.longitude), " +
            "   ll_to_earth(:latitude, :longitude) " + 
            ") < :radius",
            nativeQuery = true)

【讨论】:

@AradGonen 我认为这是因为InheritanceType.JOINED。当您将结果集映射到 class 时,它会要求提供某种 discriminator column,这在 nativeQuery=true 中没有提供。但我也不知道为什么它对派生类有效,对超类无效。 太棒了,谢谢你,它也适用于 mysql 也适用于@Inheritance(strategy = TABLE_PER_CLASS)【参考方案2】:

您应该在查询中使用类名而不是表名。将 place 更改为 PlaceEntity

@Query(value = "" +
    "SELECT * " +
    "FROM place JOIN google_place ON google_place.id = place.id " +
    "WHERE earth_distance( " +
    "   ll_to_earth(place.latitude, place.longitude), " +
    "   ll_to_earth(:latitude, :longitude) " + 
    ") < :radius",
    nativeQuery = true)
List<GooglePlaceEntity> findNearby(@Param("latitude") Float latitude,
                               @Param("longitude") Float longitude,
                               @Param("radius") Integer radius);

【讨论】:

以上是关于PSQLException:在此 ResultSet 中找不到列名 clazz_的主要内容,如果未能解决你的问题,请参考以下文章

PSQLException:错误:tsquery 中的语法错误

Heroku 上的 PSQLException

org.postgresql.util.PSQLException:连接尝试失败

PSQLException:错误:在或附近出现语法错误

PSQLException:此 ResultSet 已关闭

PSQLException:错误:关系“表”不存在