我在一个看似简单的Hibernate用例中遇到了困难,无法弄清楚发生了什么:
这是我的实体:
@Entity
@Data
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Event {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private int id;
@Column(columnDefinition = "timestamp without time zone", nullable = false)
@Temporal(TemporalType.TIMESTAMP)
private Date date;
@Column(columnDefinition = "text")
private String status;
public Event() {}
}
这是我的本地查询,用可能为NULL的“date”调用:
@Query(value = "SELECT e FROM Event e WHERE :date is null or DATE(e.date) = :date")
Page<Event> findEvents(Pageable pageable, @Param("date") Date date);
传递到函数的日期参数已经被截断为日期格式(即没有小时、分钟等),但是数据库条目不是这样,因此我在比较的左侧使用了DATE() SQL函数。当运行一个空日期查询时,会出现以下错误:
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: date = bytea
Indice : No operator matches the given name and argument type(s). You might need to add explicit type casts.
据我所知,SQL标准不会执行条件短路运算,因此第二个部分总是会被计算。另一方面,由于日期类型为null,Hibernate无法推断出“date”类型,因此将其作为二进制注入请求,导致错误。
我尝试了同样的变体,结果相同:
@Query(value = "SELECT e FROM Event e WHERE :date is null or DATE(e.date) = COALESCE(:date, '2000-01-01')")
Page<Event> findEvents(Pageable pageable, @Param("date") Date date);
编辑: 我也尝试了这个:
@Query(value = "SELECT e FROM Event e WHERE :date is null or DATE(e.date) = CAST(:date AS date)")
还有另一个反映同样问题的错误:
Caused by: org.postgresql.util.PSQLException: ERROR: cannot cast type bytea to date
编辑2:
为确保当参数为NULL时第二个条件部分不被评估,我尝试了这种方法,使用CASE WHEN .. THEN语法:
@Query(value = "SELECT e FROM Event e WHERE (case when :date is null then true else (DATE(e.date) = cast(:date AS date)) end)"
但是Hibernate不喜欢它,我不知道为什么...
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected AST node: case near line 1, column 30 [SELECT e FROM Event e WHERE (case when :date is null then true else (DATE(e.date) = cast(:date AS date)) end)]
Page<Event> findEvents(Pageable pageable, @Param("date") @Temporal java.util.Date date);
这可能会引起Spring将参数设置为 "Datenull
"。 - Tobias Liefke