【问题标题】:LocalDate between using JPA 2.1 Criteria API使用 JPA 2.1 Criteria API 之间的 LocalDate
【发布时间】:2018-06-04 08:02:50
【问题描述】:

在我的实体中,我有两个字段:

private LocalDate startDate = LocalDate.of(1900, 1, 1);
private LocalDate endDate = LocalDate.of(3000, 1, 1);

使用 JPA Criteria API 我想选择 LocalDate.now() > startDateLocalDate.now() < endDate 所在的实体。

我尝试如下:

predicates.add(builder.greaterThan(LocalDate.now(), path.<LocalDate> get(Entity_.startDate)));
predicates.add(builder.lessThan(builder.currentDate(), path.<LocalDate> get(Entity_.endDate)));

但我收到此错误:

The method greaterThan(Expression<? extends Y>, Expression<? extends Y>) in the type CriteriaBuilder is not applicable for the arguments (LocalDate, Path<LocalDate>)

我也试过了:

predicates.add(builder.between(builder.currentDate(), path.<LocalDate> get(Entity_.startDate), path.<LocalDate> get(Entity_.endDate)));

我得到以下错误:

The method between(Expression<? extends Y>, Expression<? extends Y>, Expression<? extends Y>) in the type CriteriaBuilder is not applicable for the arguments (Expression<Date>, Path<LocalDate>, Path<LocalDate>)

我该如何解决这个问题?

【问题讨论】:

  • 不是 100% 确定,但您可能应该使用 greaterThan(Expression&lt;? extends Y&gt; x, Y y) 方法,其中首先是表达式,其次是普通变量。因此,您可能需要更改参数的顺序并将LocalDate.now() 作为第二个参数。 lessThan 方法和其他方法相同。

标签: java jpa jpa-2.1 jpa-criteria


【解决方案1】:

您似乎需要AttributeConverter,因为JPA 2.1 尚不直接支持LocalDate。假设你有一个 Entity 喜欢

@Entity
@Getter
public class LocalDateEntity {
   @Id
   @GeneratedValue
   private Long id;
   @Setter
   private LocalDate startDate = LocalDate.of(1900, 1, 1);
   @Setter
   private LocalDate endDate = LocalDate.of(3000, 1, 1);
}

你可以像AttributeConverter一样使用

// import java.sql.Date not java.util.Date;
@Converter(autoApply = true) // this makes it to apply anywhere there is a need
public class LocalDateConverter implements AttributeConverter<LocalDate, Date> {

   @Override
   public Date convertToDatabaseColumn(LocalDate date) {
      return Date.valueOf(date);
   }

   @Override
   public LocalDate convertToEntityAttribute(Date value) {      
      return value.toLocalDate();
   }
}

之后就可以让CriteriaQuery点赞

CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<LocalDateEntity> cq = cb.createQuery(LocalDateEntity.class);
Root<LocalDateEntity> from = cq.from(LocalDateEntity.class);
Expression<Date> expCurrDate = cb.currentDate();
cq.where(
      cb.and(
            cb.greaterThan(from.get("endDate"), expCurrDate)
            ,cb.lessThan(from.get("startDate"), expCurrDate)
           // OR for example
           // cb.lessThan(expCurrDate, from.get("endDate"))
           // ,cb.greaterThan(expCurrDate, from.get("startDate"))
           // both are expressions no matter in what order
           // but note the change in Predicate lt vs. gt
      )
);
TypedQuery<LocalDateEntity> tq = em.createQuery(cq);

注意:虽然谓词between(..) 也可以工作,但有点不同。它包括开始和结束日期。

【讨论】:

    【解决方案2】:

    如果有人遇到这个问题,
    就像@OH GOD SPIDERS评论的一样,builder.greaterThan(LocalDate.now(), path.&lt;LocalDate&gt;get(Entity_.startDate))中的参数顺序是错误的。
    大于和小于首先期望表达式,然后是 the value (or another expression)。

    predicates.add(builder.lessThan(path.<LocalDate>get(Entity_.startDate), LocalDate.now()));
    predicates.add(builder.greaterThan(path.<LocalDate> get(Entity_.endDate), LocalDate.now()));
    

    会成功的。
    如果您认为由于切换不等式而降低了代码的可读性,您还可以选择将 LocalDate.now 包装在 builder.literal() 中:

    predicates.add(builder.greaterThan(builder.literal(LocalDate.now()), path.<LocalDate> get(Entity_.startDate)));
    predicates.add(builder.lessThan(builder.literal(LocalDate.now()), path.<LocalDate> get(Entity_.endDate)));
    

    由于LocalDate.now()builder.currentDate() 可能由于多种原因不会返回相同的日期,因此使用Expression typecasting 也可能很有趣:

    predicates.add(builder.greaterThan(builder.currentDate().as(LocalDate.class), path.<LocalDate> get(Entity_.startDate)));
    predicates.add(builder.lessThan(builder.currentDate().as(LocalDate.class), path.<LocalDate> get(Entity_.endDate)));
    

    而且,就像@pirho 指出的那样,使用between 会给你带来一天错误。

    【讨论】:

      猜你喜欢
      • 2020-09-11
      • 1970-01-01
      • 1970-01-01
      • 2014-02-19
      • 2012-08-19
      • 2013-06-21
      • 1970-01-01
      • 2011-01-31
      相关资源
      最近更新 更多