cir*_*rvo 9 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;
}
Run Code Online (Sandbox Code Playgroud)
@Query("SELECT e FROM Element e WHERE (:uuids) IS NULL OR e.uuid IN (:uuids)")
List<Element> findByUuidIn(@Param("uuids") Collection<UUID> uuids);
Run Code Online (Sandbox Code Playgroud)
elementRepository.findByUuidIn(List.of(UUID.randomUUID())); // works fine!
elementRepository.findByUuidIn(null); // -> Throws exception
Run Code Online (Sandbox Code Playgroud)
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [OTHER] - [null]
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [OTHER] - [null]
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
将查询参数更改为 String 并在查询中转换列类型。
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [OTHER] - [null]
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [OTHER] - [null]
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [1] as [VARCHAR] - [null]
org.hibernate.type.descriptor.sql.BasicBinder - binding parameter [2] as [VARCHAR] - [null]
Run Code Online (Sandbox Code Playgroud)
nullUUID 集合作为参数并进行检查IS NULL?UUID使用它吗?OTHERnullOTHER?Ste*_*rnK 10
Hibernate 有映射到的三种基本类型java.util.UUID:
org.hibernate.type.UUIDBinaryType映射到二进制数据类型( bytea)
org.hibernate.type.UUIDCharType映射到CHAR,也可以读取VARCHAR
org.hibernate.type.PostgresUUIDType通过映射到 PostgreSQL UUIDTypes#OTHER ,它符合 PostgreSQL JDBC 驱动程序定义。
很多 PostgreSQL 类型映射到java.sql.Types.OTHER,例如org.postgresql.util.Pgobject(位变化)、org.postgresql.geometric.Pgpoint(点)、org.postgresql.geometric.Pgbox(框)、java.util.UUID(uuid)……(参见此)。因此,当您传递时,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);
Run Code Online (Sandbox Code Playgroud)
它将允许您用作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 (?)
Run Code Online (Sandbox Code Playgroud)
create table ELEMENT
(
id bytea,
...
);
Run Code Online (Sandbox Code Playgroud)
然后按以下方式映射此列:
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;
// ...
}
Run Code Online (Sandbox Code Playgroud)
然后您将能够在不进行任何转换的情况下查询它:
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();
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15323 次 |
| 最近记录: |