java - Hibernate/JPA - 使用 IS NULL 比较时 UUID 的集合无法确定数据类型

标签 java postgresql hibernate spring-data-jpa

我正在使用 Spring Boot PostgreSQL JDBC 42.2.13 hibernate 5.3.18.Final ,而且似乎在添加 IS NULL 时检查 UUID 集合,Hibernate/PostgreSQL 无法确定集合的数据类型。
实体

class Element {
    @Column
    private UUID uuid;
}
存储库
@Query("SELECT e FROM Element e WHERE (:uuids) IS NULL OR e.uuid IN (:uuids)")
    List<Element> findByUuidIn(@Param("uuids") Collection<UUID> uuids);
查询执行
elementRepository.findByUuidIn(List.of(UUID.randomUUID())); // works fine!
elementRepository.findByUuidIn(null); // -> Throws exception
来自跟踪记录的参数绑定(bind)
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [OTHER] - [null]
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [OTHER] - [null]
异常(exception)
Caused by: org.postgresql.util.PSQLException: ERROR: could not determine data type of parameter $1
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2532)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:2267)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:312)
    at org.postgresql.jdbc.PgStatement.executeInternal(PgStatement.java:448)
    at org.postgresql.jdbc.PgStatement.execute(PgStatement.java:369)
    at org.postgresql.jdbc.PgPreparedStatement.executeWithFlags(PgPreparedStatement.java:153)
    at org.postgresql.jdbc.PgPreparedStatement.executeQuery(PgPreparedStatement.java:103)
    at jdk.internal.reflect.GeneratedMethodAccessor582.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114)
    at com.sun.proxy.$Proxy398.executeQuery(Unknown Source)
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:60)
    ... 114 common frames omitted
临时解决方案
将查询参数更改为字符串并在查询中转换列类型。
@Query("SELECT e FROM Element e WHERE (:uuids) IS NULL OR CAST(e.uuid AS string) IN (:uuids)")
    List<Element> findByUuidIn(@Param("uuids") Collection<String> uuids);
elementRepository.findByUuidIn(null); // works fine!
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [null]
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [VARCHAR] - [null]
向社区提问
  • 有没有办法提供null UUID 的集合作为参数并具有 IS NULL查看?
  • 是否是 Hibernate 中未绑定(bind)参数类型的错误 UUID并使用 OTHER改为使用 null 时集合作为参数?
  • 是否是PostgreSQL JDBC 中使用OTHER 时无法确定参数类型的错误?类型?
  • 最佳答案

    Hibernate 有三个 basic types映射到 java.util.UUID :

  • org.hibernate.type.UUIDBinaryType映射到 binary data types ( bytea )
  • org.hibernate.type.UUIDCharType映射到 CHAR ,也可以阅读VARCHAR
  • org.hibernate.type.PostgresUUIDType映射到 PostgreSQL UUID , 通过 Types#OTHER ,它符合 PostgreSQL JDBC 驱动程序定义。

  • 很多 PostgreSQL 类型映射到 java.sql.Types.OTHER ,例如 org.postgresql.util.Pgobject (位变化),org.postgresql.geometric.Pgpoint (点), org.postgresql.geometric.Pgbox (箱), java.util.UUID (uuid), ...(见 this)。因此,PostgreSQL JDBC 驱动程序在您传递null 时无法确定参数的数据类型。 .
    解决方案
  • 您可以通过以下方式更正您的查询:

  • @Query("SELECT e FROM Element e WHERE (:uuids) IS NULL OR CAST(e.uuid as org.hibernate.type.UUIDCharType) IN (:uuids)")
    List<Element> findByUuidIn(@Param("uuids") Collection<UUID> uuids);
    
    它将允许您使用 Collection<UUID>作为传递的参数类型。但是,实际上这与您的解决方法类似,因为它会生成以下 sql:
    select
       element0_.id as id1_2_ 
    from TEST_SCHEMA.ELEMENT element0_ 
    where  ? is null or cast(element0_.id as varchar(255)) in (?)
    
  • 您可以更改表的列定义:

  • create table ELEMENT
    (
       id bytea,
       ...
    );
    
    然后按以下方式映射此列:
    import org.hibernate.annotations.Type;
    
    @Entity
    public class Element
    {
       @Id
       @GeneratedValue
       @Type(type = "uuid-binary") // This is pg-uuid by default for PostgreSQL82Dialect and higher
       private UUID id;
    
       // ...
    }
    
    然后你就可以在不进行任何转换的情况下查询它:
    Collection<UUID> uuids = null;
    
    List<Element> elements = em.createQuery(
       "select e from Element e where (:uuids) is null or e.id in (:uuids)",
       Element.class)
    .setParameter("uuids", uuids)
    .getResultList();
    

    关于java - Hibernate/JPA - 使用 IS NULL 比较时 UUID 的集合无法确定数据类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64934337/

    相关文章:

    java - 线程 "main"java.lang.ClassNotFoundException 中的异常,mapreduce

    java:if语句表达式的非法开始

    postgresql - Postgres 数学 : Operator does not exist: bigint == integer

    spring - 在 dao 单元测试之前生成数据库表

    java - Spring hibernate : TypedQuery NullPointerException

    java - POJO 或 DTO 方法

    java - 为什么我的 MIDI 程序没有完成/关闭?

    java - 使用 JList 的 SwingUtilities invokeLater GUI 更新

    php - Yii Framework 2.0 -findModel 返回一个空对象

    sql - 如果找到几行,如何只删除一行?