首页 > 解决方案 > 使用 Criteria API 的 H2 DATEDIFF 函数问题

问题描述

有一个简单的实体Item具有两个日期类型属性:

@Entity
public class Item {

@Id
@GeneratedValue(generator = Constants.ID_GENERATOR)
protected Long id;

@NotNull
protected String name;

@NotNull
protected Date from;

@NotNull
protected Date to

我想使用 Criteria API 使用H2 数据库“DATEDIFF”的专有功能。所以我有下面的代码片段来做到这一点:

CriteriaQuery<Item> criteria = cb.createQuery(Item.class);
Root<Item> i = criteria.from(Item.class);
criteria.select(i).where(
      cb.gt(
            cb.function(
                        "DATEDIFF",
                        Integer.class,
                        cb.literal("DAY"),
                        i.get("from"),
                        i.get("to")
            ),
            1
      )
);
... // other code to handle result 

当我尝试执行查询时,出现此错误:

警告 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL 错误:90008,SQLState:90008 错误 org.hibernate.engine.jdbc.spi.SqlExceptionHelper - 参数“parameterIndex”[90008-200] 的无效值“1” org.h2.message.DbException.getJdbcSQLException(DbException.java:590) 在 org.h2.message.DbException.getJdbcSQLException(DbException.java:429) 在 org.h2.message.DbException.get(DbException.java:205)在 org.h2.message.DbException.getInvalidValueException(DbException.java:280) 在 org.h2.jdbc.JdbcPreparedStatement.setParameter(JdbcPreparedStatement.java:1503) 在 org.h2.jdbc.JdbcPreparedStatement.setString(JdbcPreparedStatement.java:413) ) 在 org.hibernate.type.descriptor.sql 的 org.hibernate.type.descriptor.sql.VarcharTypeDescriptor$1.doBind(VarcharTypeDescriptor.java:46)。BasicBinder.bind(BasicBinder.java:73) 在 org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:276) 在 org.hibernate.type.AbstractStandardBasicType.nullSafeSet(AbstractStandardBasicType.java:271) 在 org.hibernate.param .NamedParameterSpecification.bind(NamedParameterSpecification.java:53) at org.hibernate.loader.hql.QueryLoader.bindParameterValues(QueryLoader.java:648) at org.hibernate.loader.Loader.prepareQueryStatement(Loader.java:2120) at org. hibernate.loader.Loader.executeQueryStatement(Loader.java:2034) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:2012) at org.hibernate.loader.Loader.doQuery(Loader.java:953) at org .hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) 在 org.hibernate.loader.Loader。doList(Loader.java:2815) at org.hibernate.loader.Loader.doList(Loader.java:2797) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2629) at org.hibernate.loader.Loader .list(Loader.java:2624) 在 org.hibernate.loader.hql.QueryLoader.list(QueryLoader.java:506) 在 org.hibernate.hql.internal.ast.QueryTranslatorImpl.list(QueryTranslatorImpl.java:396) 在org.hibernate.engine.query.spi.HQLQueryPlan.performList(HQLQueryPlan.java:219) 在 org.hibernate.internal.SessionImpl.list(SessionImpl.java:1396) 在 org.hibernate.query.internal.AbstractProducedQuery.doList( AbstractProducedQuery.java:1558) 在 org.hibernate.query.internal.AbstractProducedQuery.list(AbstractProducedQuery.java:1526) 在 org.hibernate.query.Query.getResultList(Query.java:165) 在 org.hibernate.query.criteria .internal.compile。CriteriaQueryTypeQueryAdapter.getResultList(CriteriaQueryTypeQueryAdapter.java:76) 在 com.ico.ltd.querying.domain.Restriction.executeQueries(Restriction.java:329)

但如果我使用 JPQL:

 select i from Item i where function('DATEDIFF', 'DAY', i.from, i.to) > 1

它完成没有任何问题。此外,如果我将 H2 版本切换到 1.3.171,Criteria API 工作正常。我相应地使用以下版本的 H2 和 Hibernate 1.4.2005.4.8.Final。有人可以帮忙吗?

标签: javahibernateh2

解决方案


我认为你应该为你的整数值 1 使用一个文字来比较:

CriteriaQuery<Item> criteria = cb.createQuery(Item.class);
Root<Item> i = criteria.from(Item.class);
criteria.select(i).where(
      cb.gt(
            cb.function(
                        "DATEDIFF",
                        Integer.class,
                        cb.literal("DAY"),
                        i.get("from"),
                        i.get("to")
            ),
            cb.literal(1)
      )
);

推荐阅读