如何构建一个动态查询,该查询添加了迄今为止的天数,并使用条件API将该日期与另一个日期进行比较?

我有一张A桌和一张B桌。 JPA entity ,A和B类都有joda.time.datetime Persistent Field分别表示retentionDatelastmodifiedDate 。 A还有一个类型为int Persistent Field 。 现在我想将add number of a.daysa.retentionDate ,然后使用JPA criteria API将其与b.lastmodifiedDate进行比较。

实体类

 @Entity @Table(name = "A") @Data @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) @EqualsAndHashCode(of = "id", callSuper = false) public class A extends AbstractBaseEntity { @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") @Column(unique = true, length = 36) private String id; @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime") @JsonDeserialize(using = DateTimeDeserializer.class) @JsonSerialize(using = DateTimeSerializer.class) private DateTime retentionDate; private int days; } 

B实体类

 @Entity @Table(name = "B") @Data @JsonInclude(JsonInclude.Include.NON_NULL) @JsonIgnoreProperties(ignoreUnknown = true) @EqualsAndHashCode(of = "id", callSuper = false) public class B extends AbstractBaseEntity { @Id @GeneratedValue(generator = "uuid") @GenericGenerator(name = "uuid", strategy = "uuid2") @Column(unique = true, length = 36) private String id; @Type(type = "org.jadira.usertype.dateandtime.joda.PersistentDateTime") @JsonDeserialize(using = DateTimeDeserializer.class) @JsonSerialize(using = DateTimeSerializer.class) private DateTime lastmodifiedDate ; @ManyToOne(fetch = FetchType.EAGER) @JoinColumn(name = "A_ID") private A a; } 

JPA标准查询:

 CriteriaQuery b = builder.createQuery(B.class); Root fromB = criteria.from(B.class); Expression lastmodifiedDate = fromB.get(B_.lastmodifiedDate); Expression retentionDate = fromB.get(B_.a).get("retentionDate"); Expression days = fromB.get(B_.a).get("days"); Expression newDate = // how to add days in retentionDate here so it became a newDate? b.select(fromB); b.where(builder.greaterThanOrEqualTo(newDate , lastmodifiedDate) ); 

请在上面的查询中帮助我在retentionDate中添加天数。 谢谢。

您可以使用CriteriaBuilder #function()来执行数据库函数,以将days添加到retentionDate 。 我用DATEADD()做了一个例子,因为我的测试项目用H2数据库运行。

  ParameterExpression dayUnit = builder.parameter(String.class, "dayUnit"); Expression newDate = builder.function("DATEADD", DateTime.class, dayUnit, days, retentionDate); 

完整的例子:

  CriteriaBuilder builder = entityManager.getCriteriaBuilder(); CriteriaQuery cq = builder.createQuery(B.class); Root fromB = cq.from(B.class); Expression lastmodifiedDate = fromB.get(B_.lastmodifiedDate); Expression retentionDate = fromB.get(B_.a).get("retentionDate"); Expression days = fromB.get(B_.a).get("days"); ParameterExpression dayUnit = builder.parameter(String.class, "dayUnit"); Expression newDate = builder.function("DATEADD", DateTime.class, dayUnit, days, retentionDate); cq.where(builder.greaterThanOrEqualTo(newDate, lastmodifiedDate)); TypedQuery tq = entityManager.createQuery(cq.select(fromB)); tq.setParameter("dayUnit", "DAY"); List results = tq.getResultList(); 

此查询转换为SQL为:

 select b0_.id as id1_1_, b0_.a_id as a_id3_1_, b0_.lastmodified_date as lastmodi2_1_ from b b0_ cross join a a1_ where b0_.a_id=a1_.id and DATEADD(?, a1_.days, a1_.retention_date)>=b0_.lastmodified_date