Java 使用Hibernate的JPQL类型化查询中的时间戳文本

Java 使用Hibernate的JPQL类型化查询中的时间戳文本,java,hibernate,jpa,jpql,Java,Hibernate,Jpa,Jpql,有没有一种方法可以在Hibernate的JPQL查询中使用时间戳文本 有一个常量时间戳要与之比较,该时间戳应该放在JPQL查询中。 现在它是这样工作的 TypedQuery<TestEntity> query = entityManager .createQuery("select t from TestEntity t where greatest(nvl(t.f1, :nullDate), nvl(t.f2, :nullDate)) between :date1 and :dat

有没有一种方法可以在Hibernate的JPQL查询中使用时间戳文本

有一个常量时间戳要与之比较,该时间戳应该放在JPQL查询中。 现在它是这样工作的

TypedQuery<TestEntity> query = entityManager
.createQuery("select t from TestEntity t where greatest(nvl(t.f1, :nullDate), nvl(t.f2, :nullDate)) between :date1 and :date2")
.setParameter("date1", date1)
.setParameter("date2", date2)
.setParameter("nulllDate", LocalDateTime.of(1970, 1, 1, 0, 0, 0, 1))
但在运行时出错

org.hibernate.QueryException: unexpected char: '{' [select t from TestEntity t where greatest(nvl(t.f1, {ts '1970-01-01 00:00:00:000000001'}), nvl(t.f2, {ts '1970-01-01 00:00:00:000000001'})) between :startChanges and :endChanges]
我的设置是
Java 8
JPA 2.1
弹簧靴1.4.2.释放
Hibernate 5.1.0.Final(与5.2.16.Final一起复制)
甲骨文11.2


UPD:也许它不在规范中,但是使用上面的代码可以正确地将最大的/nvl函数从JPQL传递到SQL。我已尝试将
最大值
/
nvl
包装到
函数
中,但文本仍不被接受。

我已在我的环境中准备了一个测试,并返回结果:

Calendar calendar = Calendar.getInstance();
calendar.setTime(date1);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date1 = calendar.getTime();

calendar.setTime(date2);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date2 = calendar.getTime();

TypedQuery<TestEntity> query = entityManager
.createQuery("select t from TestEntity t where greatest(nvl(t.f1, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')), nvl(t.f2, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')) between :date1 and :date2")
.setParameter("date1", date1)
.setParameter("date2", date2);
Calendar Calendar=Calendar.getInstance();
日历。设置时间(日期1);
日历.set(calendar.HOUR,0);
calendar.set(calendar.MINUTE,0);
calendar.set(calendar.SECOND,0);
calendar.set(calendar.毫秒,0);
date1=calendar.getTime();
日历。设置时间(日期2);
日历.set(calendar.HOUR,0);
calendar.set(calendar.MINUTE,0);
calendar.set(calendar.SECOND,0);
calendar.set(calendar.毫秒,0);
date2=calendar.getTime();
TypedQuery=entityManager
.createQuery(“从测试实体t中选择t,其中最大(nvl(t.f1,到时间戳('1970-01-01 00:00:0000000000 1','YYYY-MM-DD HH24:MI:SS,FF9')),nvl(t.f2,到时间戳('1970-01-01-01 00:00:0000000000 1','YYYY-MM-DD HH24:MI:SS,FF9'),介于:日期1和:日期2之间))
.setParameter(“日期1”,日期1)
.setParameter(“日期2”,日期2);
我希望这就是你要找的


编辑:修改查询,将
添加到_TIMESTAMP
函数中。经@dfche确认,它正在工作

JPA规范在哪里定义了
最大的
nvl
的JPQL函数?回答:没有t@DN1我已经用一个更严格的JPQL替换了查询字符串,通过“function”调用beast/nvl,但它不会更改任何内容。它仍然接受参数并为其生成相同的SQL,同时抛出一个
意外字符:“{
文本错误。
从TestEntity t where function('magest',function('nvl',t.f1,{ts'1970-01-01 00:00:00.00000001')、function('nvl',t.f2,{ts'1970-01-01-01 00:00.00000001'))在:startChanges和:endChanges之间
我可以使用JDBC转义语法(您使用的是花括号和“ts”),而我的JPA提供程序没有问题(并且您的语法用法是有效的IMHO),例如,请尝试一个不带函数调用的简单查询,并使用JDBC escape语法检查您的JPA提供程序是否首先正确处理它,然后添加函数。@DN1我尝试了一个非常基本的查询,没有任何条件,只有一个带文本的查询。它会导致相同的错误,看起来Hibernate 5.1.0不支持lite时间戳这是早期版本的一个问题,至少听起来你需要在它们上面引起一个bug。谢谢你的代码,它对我也适用。但我试图避免将nullDate设置为参数,而是使用内联文本。你想使用字符串文本还是类?@Alberto,to_TIMESTAMP是无效的JPQL,请阅读一本JPA手册。该JPA手册会告诉您所使用的表单的“时间戳文字”是完全有效的,并且该JPA提供商不喜欢它。这对我有用:
String consulta=“从ExcepcionHistorico e中选择e WHERE best(nvl(tim_procx,TO_timestamp('2015-01-01 00:00:0000000000 1',yyyyy-MM-DD HH24:MI:SS,FF9')),nvl(tim_recept,TO_TIMESTAMP('2016-01-01 00:00:0000000000 1',YYYY-MM-DD HH24:MI:SS,FF9'))介于:date3和:date4之间。
。结果:
休眠:选择最大的位置(nvl(除PCIONH0.tim procx,TO_TIMESTAMP('2015-01-01 00:00:00:0000000000 1',YYYYYY-MM-DD HH24:SS,FF9')),nvl(除PCIONH0.tim recept)TO_时间戳('2016-01-01 00:00:0000000000 1',YYYY-MM-DD HH24:MI:SS,FF9'))介于?和?
@Alberto
TO_TIMESTAMP
之间,非常好,谢谢。根据我的(非常简短的)测试,就本机SQL选择而言,这两种形式(
TIMESTAMP
/
TO_TIMESTAMP
)之间没有性能差异。
Calendar calendar = Calendar.getInstance();
calendar.setTime(date1);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date1 = calendar.getTime();

calendar.setTime(date2);
calendar.set(Calendar.HOUR, 0);
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MILLISECOND, 0);

date2 = calendar.getTime();

TypedQuery<TestEntity> query = entityManager
.createQuery("select t from TestEntity t where greatest(nvl(t.f1, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')), nvl(t.f2, TO_TIMESTAMP('1970-01-01 00:00:00,000000001', 'YYYY-MM-DD HH24:MI:SS,FF9')) between :date1 and :date2")
.setParameter("date1", date1)
.setParameter("date2", date2);