如何修复 Hibernate 中的命名查询错误(意外标记:DAY)?
How to fix Named Query Error ( unexpected token: DAY ) in Hibernate?
以下是我用于查找超过 90 天的活动的命名查询:
"DELETE FROM PAActivity pa WHERE pa.status IN (:statusSet) AND cast(pa.datoFinish as date) < cast(DATE_SUB(current_date(), INTERVAL (:noofdays) DAY) as date)"
在编译期间,它给出了以下 Hibernate 异常:
ERROR 2018-04-24 11:00:07,579 o.h.h.i.a.ErrorCounter - line 1:243: unexpected token: DAY
ERROR 2018-04-24 11:00:07,579 o.h.h.i.a.ErrorCounter - line 1:243: unexpected token: DAY
line 1:243: unexpected token: DAY
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:876)
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3472)
at org.hibernate.hql.internal.antlr.HqlBaseParser.unaryExpression(HqlBaseParser.java:3250) .
.
.
.
.
WARN 2018-04-24 11:00:07,641 o.h.h.i.a.HqlParser - HHH000203: processEqualityExpression() : No expression to process!
ERROR 2018-04-24 11:00:08,094 o.h.i.SessionFactoryImpl - HHH000177: Error in named query: deletePAActivityByProcessIDs
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: DAY near line 1, column 243 [DELETE FROM fn.gover.model.PAActivity pa WHERE pa.status IN (:statusSet) AND cast(pa.datoFinish as date) < cast(DATE_SUB(current_date(), INTERVAL (:noofdays) DAY) as date)]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
我认为问题是 HQL 不支持 INTERVAL
您可以通过两种方式解决您的问题。
第一 - RestrictionCriteria
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_YEAR, -90);
Criteria criteria = session.createCriteria(Yourclass.class);
criteria.add(Restrictions.ge("datoFinish", c.getTime());
List results = criteria.list();
或者像这样更改您的查询:
AND cast(pa.datoFinish as date) < cast(:dateMinus90 as date)
并将参数设置为日历的结果
.setParameter("dateMinus90", c.getTime())
第二种方法是继承方言class并注册sql函数。例如 Oracle。
public class MyOracleDialect extends Oracle10gDialect {
@Override
protected void registerFunctions() {
super.registerFunctions();
registerFunction("sub_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, " date_sub(?1, INTERVAL ?2 DAY)"));
} }
然后在 hibernate props 中你应该使用这个方言。但我认为这不是最好的方法。
以下是我用于查找超过 90 天的活动的命名查询:
"DELETE FROM PAActivity pa WHERE pa.status IN (:statusSet) AND cast(pa.datoFinish as date) < cast(DATE_SUB(current_date(), INTERVAL (:noofdays) DAY) as date)"
在编译期间,它给出了以下 Hibernate 异常:
ERROR 2018-04-24 11:00:07,579 o.h.h.i.a.ErrorCounter - line 1:243: unexpected token: DAY
ERROR 2018-04-24 11:00:07,579 o.h.h.i.a.ErrorCounter - line 1:243: unexpected token: DAY
line 1:243: unexpected token: DAY
at org.hibernate.hql.internal.antlr.HqlBaseParser.primaryExpression(HqlBaseParser.java:876)
at org.hibernate.hql.internal.antlr.HqlBaseParser.atom(HqlBaseParser.java:3472)
at org.hibernate.hql.internal.antlr.HqlBaseParser.unaryExpression(HqlBaseParser.java:3250) .
.
.
.
.
WARN 2018-04-24 11:00:07,641 o.h.h.i.a.HqlParser - HHH000203: processEqualityExpression() : No expression to process!
ERROR 2018-04-24 11:00:08,094 o.h.i.SessionFactoryImpl - HHH000177: Error in named query: deletePAActivityByProcessIDs
org.hibernate.hql.internal.ast.QuerySyntaxException: unexpected token: DAY near line 1, column 243 [DELETE FROM fn.gover.model.PAActivity pa WHERE pa.status IN (:statusSet) AND cast(pa.datoFinish as date) < cast(DATE_SUB(current_date(), INTERVAL (:noofdays) DAY) as date)]
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:54)
at org.hibernate.hql.internal.ast.QuerySyntaxException.convert(QuerySyntaxException.java:47)
我认为问题是 HQL 不支持 INTERVAL
您可以通过两种方式解决您的问题。 第一 - RestrictionCriteria
Calendar c = Calendar.getInstance();
c.add(Calendar.DAY_OF_YEAR, -90);
Criteria criteria = session.createCriteria(Yourclass.class);
criteria.add(Restrictions.ge("datoFinish", c.getTime());
List results = criteria.list();
或者像这样更改您的查询:
AND cast(pa.datoFinish as date) < cast(:dateMinus90 as date)
并将参数设置为日历的结果
.setParameter("dateMinus90", c.getTime())
第二种方法是继承方言class并注册sql函数。例如 Oracle。
public class MyOracleDialect extends Oracle10gDialect {
@Override
protected void registerFunctions() {
super.registerFunctions();
registerFunction("sub_days", new SQLFunctionTemplate(StandardBasicTypes.DATE, " date_sub(?1, INTERVAL ?2 DAY)"));
} }
然后在 hibernate props 中你应该使用这个方言。但我认为这不是最好的方法。