春季启动 - 工作日计数查询



我的用例:

我们有一个安装
  • 计划实体(检查下面的代码),它有一个安装日期。

  • 安装
  • 完成后,我们将在4个工作日后与客户核实安装状态。 注意:(4 个工作日 - 此计数是可配置的。所以"X"工作日)

工作日是指 - 周一至周五。我们不关心其他假期。

  • 我有一个调度程序,它会在"X"工作日后检索这些订单 -我被困在这里

我不知道如何在"X"工作日之后进行查询。

我的代码:

@Entity
@Table(schema = "myschema", name = "installation_dates")
@Getter
@Setter
@NoArgsConstructor
public class InstallDates extends TransEntity implements Serializable {
// other columns
@Column(name = "installation_schedule_datetime")
private LocalDateTime installationScheduleDatetime;//I use this column for calculation
@Formula("getWeekDaysCount(installationScheduleDatetime)")
private int weekDaysCount;

public  int getWeekDaysCount(LocalDateTime installationScheduleDatetime) {
int totalWeekDays = 0;
LocalDateTime todayDate = LocalDateTime.now();
while (!installationScheduleDatetime.isAfter(todayDate)) {
switch (installationScheduleDatetime.getDayOfWeek()) {
case FRIDAY:
case SATURDAY:
break;
default:
totalWeekDays++;
break;
}
installationScheduleDatetime = installationScheduleDatetime.plusDays(1);
}
return totalWeekDays;
}
}

问题:

如何对工作日进行 SQL 或 JPQL 或 JPA 查询?

我知道它非常基本的问题,我是一名移动应用程序开发人员,我最近加入了Springboard团队,这对我来说真的很难:(

请随时提供您宝贵的反馈!

如果我正确解决了问题,我有以下建议。

爪哇岛:

  1. 以当前日期为准
  2. 找到date of interest:计数减去 4 个工作日(所以如果今天是星期五 - 减去 4 天,如果是星期一 - 周末减去 2 天,工作日再减 4 天)

然后编写一个查询,该查询将选择在感兴趣的日期完成的所有安装。 在伪代码中:
select * from installations where installation_date = <date of interest>;.

感兴趣的日期 Java 代码:

public LocalDateTime getDateOfInterest(int workdays) {
LocalDateTime currentDate = LocalDateTime.now();
if (workdays < 1) {
return currentDate;
}
//it will subtract 'X' working days from current date
LocalDateTime result = currentDate;
int addedDays = 0;
while (addedDays < workdays) {
result = result.minusDays(1);
if (!(result.getDayOfWeek() == DayOfWeek.FRIDAY ||
result.getDayOfWeek() == DayOfWeek.SATURDAY)) {
++addedDays;
}
}
return result;
}

首先让我们回答您的问题

  1. 不,您不能从@Formula调用方法
  2. 您可能可以(请参阅此处,但这可能取决于您的数据库。

使用实体和 JPA 的事实并不意味着所有内容都必须是 JPA 属性。

您可以:

  1. 编写一个动态计算它的 get 方法
  2. 写一个懒惰地设置它的 getter。
  3. 使用@PostLoad始终设置它。
@Entity
@Table(schema = "myschema", name = "installation_dates")
@Getter
@Setter
@NoArgsConstructor
public class InstallDates extends TransEntity implements Serializable {
// other columns
@Column(name = "installation_schedule_datetime")
private LocalDateTime installationScheduleDatetime;//I use this column for calculation

public int getWeekDaysCount() {
int totalWeekDays = 0;
LocalDateTime isdt = this.installationScheduleDatetime;
LocalDateTime todayDate = LocalDateTime.now();
while (!isdt.isAfter(todayDate)) {
switch (isdt.getDayOfWeek()) {
case FRIDAY:
case SATURDAY:
break;
default:
totalWeekDays++;
break;
}
isdt = isdt.plusDays(1);
}
return totalWeekDays;
}
}

或者,如果您真的希望它是一个属性,则可以使用 getter 懒惰地设置它。

@Entity
@Table(schema = "myschema", name = "installation_dates")
@Getter
@Setter
@NoArgsConstructor
public class InstallDates extends TransEntity implements Serializable {
// other columns
@Column(name = "installation_schedule_datetime")
private LocalDateTime installationScheduleDatetime;//I use this column for calculation

private int weekDaysCount = -1;
public int getWeekDaysCount() {
if (weekDaysCount == -1) {
int totalWeekDays = 0;
LocalDateTime isdt = this.installationScheduleDatetime;
LocalDateTime todayDate = LocalDateTime.now();
while (!isdt.isAfter(todayDate)) {
switch (isdt.getDayOfWeek()) {
case FRIDAY:
case SATURDAY:
break;
default:
totalWeekDays++;
break;
}
isdt = isdt.plusDays(1);
}
weekDaysCount = totalWeekDays;
}
return weekDaysCount;
}
}

或者,如果您总是想计算该值,您甚至可以将其放在方法的@PostLoad注释中以初始化它(您甚至可以重用上面的惰性getter)。或者将 init 代码移动到@PostLoad注释方法。

@PostLoad
private void initValues() {
getWeekDaysCount();
}

>@Formula指定用本机SQL编写的表达式,该表达式用于读取属性的值,而不是将值存储在列中。(https://docs.jboss.org/hibernate/orm/current/javadocs/org/hibernate/annotations/Formula.html)

至于您的情况,如果weekDaysCount是从installationScheduleDatetime派生的,那么在数据库中存储似乎没有多大用处。我只是将weekDaysCount标记为@Transient并完成它(应该删除@Formula)。

另一种解决方案是将weekDaysCount保持非瞬态状态,并将计算置于@PreUpdate/@PrePersist方法中。有关此内容的更多信息,请参阅 https://www.baeldung.com/jpa-entity-lifecycle-events。

最新更新