JPA Criteria API - 使用 ORACLE 将天数添加到 DATE

alb*_*iff 6 oracle jpa oracle10g criteria-api

我正在尝试使用 JPA Criteria API 来过滤特定范围之间的日期。

问题是我的实体中没有直接日期,我使用日期字段获取日期并将天数(在另一个字段中)添加到该日期。

我环顾四周,看到一些建议在将日期传递给标准构建器之前先用 java 计算日期,但问题是我不知道要添加的天数,因为它取决于特定列中的天数桌子。

简化的表 OBJECT 有一个类型为 date 的字段 CREATION_DATE 和一个数字类型的 EXPIRATION_DAYS。我想通过一系列可能的到期日期进行过滤,我得到了 OBJECT 表中每个元素的到期日期,将 EXPIRATION_DAYS 添加到 CREATION_DATE,SQL 查询是:

select * from OBJECT
where CREATION_DATE + EXPIRATION_DAYS 
between to_date('01/01/2018','dd/MM/yyyy') and to_date('01/02/2018','dd/MM/yyyy') 
Run Code Online (Sandbox Code Playgroud)

CriteriaBuilder我做了一些尝试,但我想我尽量用最好的方法是如下:

 CriteriaBuilder criteriaBuilder = entityManager.getCriteriaBuilder();
 CriteriaQuery<Object> criteria = criteriaBuilder.createQuery(Object.class);
 List<Predicate> predicates...
 predicates.add(criteriaBuilder.between(
        criteriaBuilder.function("AddDate", Date.class, Object.get("creationDate"), criteriaBuilder.literal("day"), Object.get("expirationDays")), 
        dateInit, dateEnd));
 criteria.where(predicates.toArray(new Predicate[]{}));        
 ...
  TypedQuery<Object> query = entityManager.createQuery(criteria);
  return query.getResultList();
Run Code Online (Sandbox Code Playgroud)

我使用function("addDate"...)方法,问题是我认为 JPA 实现将“addDate”转换为特定的数据库供应商,但事实并非如此,因为它抛出了以下非常清楚的异常:

javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.6.4.v20160829-44060b6): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: java.sql.SQLSyntaxErrorException: ORA-00904: "ADDDATE": invalid identifier
Run Code Online (Sandbox Code Playgroud)

和查询跟踪:

(AddDate(t0.CREATION_DATE, ?, t0.EXPIRATION_DAYS) BETWEEN ? AND ?)).

如何使用 ORACLE 作为数据库来实现这一点?或者有更好的方法吗?

alb*_*iff 0

Hibernate中似乎有一个@Formula注释提供了我正在寻找的功能,但是在 JPA 中没有这样的东西,在我使用的具体实现中也没有这样的东西(eclipselink)。

我想避免声明特定函数的必要性,但不幸的是我这样做,首先我ADD_DAYS在Oracle中声明该函数如下:

create or replace function ADD_DAYS(dateValue DATE, daysValue NUMBER)
return DATE is
begin
    return dateValue + daysValue;
end;
Run Code Online (Sandbox Code Playgroud)

然后,我使用 方法调用该函数functioncriteriaBuilder并传递函数名称、oracle 函数返回的对象类型以及我定义的两个参数(包含日期的列和包含要添加的天数的列)作为参数:

criteriaBuilder.function("ADD_DAYS", Date.class, Object.get("creationDate"), Object.get("expirationDays"))
Run Code Online (Sandbox Code Playgroud)