java - 当 NULL LocalDate 作为输入给出时, native 命名查询失败并出现异常 "column is of type date but expression is of type bytea"

标签 java postgresql hibernate spring-data

查询:

    INSERT INTO PERSON 
        (email, mobile, party_id, affiliate_id, eligibility, member_start_date, created_by, created_dt, first_name, last_name, google_connected) 
        values 
        ('xxx@yyy.org', NULL, 123, '123', '1', NULL, NULL, '2018-8-30 21:45:56.859000 -6:0:0', 'xxx', 'yyy', '0')
        ON CONFLICT (email) 
        DO UPDATE SET create_dt = '2018-8-30 21:45:56.859000 -6:0:0' where email = ?

当 LocalDate 值不为 null 时,它工作正常。仅当 LocalDate 值为 null 时才会面临此问题。

即使在 PostgreSQL 转换之后,它也会执行相同的操作。

异常堆栈跟踪:

2018-08-30 21:10:48,372 -- [ERROR]-- There was an unexpected problem with your request org.postgresql.util.PSQLException: ERROR: column "member_start_date" is of type date but expression is of type bytea
Hint: You will need to rewrite or cast the expression. Position: 185 at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2182) at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1911) at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:645) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:495) at org.postgresql.jdbc2.AbstractJdbc2Statement.executeQuery(AbstractJdbc2Statement.java:380) at sun.reflect.GeneratedMethodAccessor98.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.apache.tomcat.jdbc.pool.StatementFacade$StatementProxy.invoke(StatementFacade.java:114) at com.sun.proxy.$Proxy185.executeQuery(Unknown Source) at at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:70) ... 149 common frames omitted

实体:

@Entity(name = "person")
@EqualsAndHashCode(callSuper = false)
public class PersonEntity extends Audit {

@Id
@GeneratedValue
@Column(name = "person_id", columnDefinition = "uuid", updatable = false)
private UUID id;

@Column(name = "first_name")
private String firstName;

@Column(name = "last_name")
private String lastName;

@Column(name = "email")
@NotNull
private String email;

@Column(name = "mobile")
private String mobile;

@Column(name = "party_id")
private Long partyId;

@Column(name = "affiliate_id")
private String affiliateId;

@Column(name = "eligibility")
@NotNull
private Boolean eligibility;

@Column(name = "member_start_date")
private LocalDate memberStartDate;

@Column(name = "google_connected")
private Boolean googleAccountConnected;
}

PostgreSQL 表定义;它缺少不重要的 google_connected 列:

CREATE TABLE person
( 
   person_id             UUID NOT NULL,
   email                 VARCHAR(128) NOT NULL,
   mobile                VARCHAR(20), 
   party_id              INTEGER,
   affiliate_id          VARCHAR(20),
   eligibility              BOOLEAN NOT NULL,
   member_start_date     DATE, 
   created_by            VARCHAR(128) NOT NULL,
   created_dt            TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
   updated_by            VARCHAR(128) DEFAULT NULL,
   updated_dt            TIMESTAMP NULL,
   CONSTRAINT person_pk PRIMARY KEY ( person_id )
 );

最佳答案

因为查询是 native 的,Hibernate 不知道期望的数据类型,所以当您传递 null 时,它默认为通用的 Serializable 类型处理程序。更改此行为会破坏与其他数据库的兼容性。

但是 Postgres 会立即解析查询并确定可接受的类型,并且它总是在检查 null 之前检查类型。他们是唯一可以解决这个问题的人,但他们拒绝这样做并说它按预期工作。

唯一适合您的解决方案是:

  • 使用 JPQL
  • 使用托管实体
  • 在需要的查询字符串中使用硬编码的空值

幸运的是,对于第三个选项,借助 Hibernate,您可以在 native 查询中使用命名参数,因此您不必为某些内容何时可用和何时不进行位置计算。

编辑:我发现的第四个解决方案。

您有您的问题:

Query q = em.createNativeQuery("UPDATE...");

在某处有一些静态的最终 LocalDate 对象:

public static final LocalDate EPOCH_DATE = LocalDate.of(1970, 1, 1);

然后像这样调用查询:

q.setParameter("start_date", EPOCH_DATE);
q.setParameter("start_date", nullableDateParam);

第一次为参数调用 setParameter 时,Hibernate 使用该类来解析类型。第二次调用它时,类型已经解析,因此 null 将起作用。

关于java - 当 NULL LocalDate 作为输入给出时, native 命名查询失败并出现异常 "column is of type date but expression is of type bytea",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52108442/

相关文章:

ruby-on-rails - 用完全匹配的词搜索

sql - 在gral HQL中,我将如何使用(非聚合的)Oracle函数?

java - hql 的字符串分割函数

java - 如何从父类(super class)对象调用子类方法

java - 如何在java中使用我自己的密码和aes

java - 通过 web 代理使用 restful webservice

java - Mockito:在 X 调用上返回 NULL

python - 无法获得索引 psycopg2 的定义

由 sql 填充的 Python 表单下拉选项

java - JPA:具有复合主键的持久实体