java byte 不等于空_关于java:以NULL LocalDate作为输入时,本地命名查询失败,并出现异常“列的类型为date但表达式的类型为bytea”...

查询:

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强制转换之后,它也会执行相同的操作。

异常stacktrace:

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 )

);

您可以分享您的实体类吗?

向我们展示Postgres中的表定义可能会有所帮助。

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

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

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

使用JPQL

使用管理实体

在需要的查询字符串中使用硬编码的空值

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

编辑:从那以后我发现的第四个解决方案。

您有查询:

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。

知道为什么仅在日期列而不是其他列会发生此问题吗?

取决于Postgres中具有哪些隐式类型转换函数。 您可以使用\dC在psql控制台中列出它们,尽管我不了解。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值