【发布时间】:2016-03-05 10:31:55
【问题描述】:
我正在使用带有 ebean 的播放框架 2.3.4。我的数据库中有这两个表:
@Entity
public class Device extends Model {
@Id
public Long id;
@OneToMany(mappedBy = "device")
public List<DeviceInactivePeriod> inactivePeriods = new ArrayList<DeviceInactivePeriod>();
...
}
@Entity
public class DeviceInactivePeriod extends Model {
@Id
public Long id;
@Constraints.Required
@Formats.DateTime(pattern = "dd-MM-yyyy HH:mm")
public Date start;
@Formats.DateTime(pattern = "dd-MM-yyyy HH:mm")
public Date end;
@ManyToOne
public Device device;
...
}
将DeviceInactivePeriod 对象想象为一个时间段,其中设备处于非活动状态。 DEVICE 包含它们的列表。
现在我想查询所有设备,在特定时刻(例如现在)没有DeviceInactivePeriod(这意味着设备处于活动状态)
我尝试了很多很多东西,但都没有成功。我有这个问题:
Date now = new Date();
return
find.where().
and(
Expr.le("inactivePeriods.start", now),
Expr.ge("inactivePeriods.end", now)
)
.orderBy(sorting + " " + order)
.findPagingList(Global.PAGE_SIZE_DEVICES)
.setFetchAhead(false)
.getPage(page);
准确返回所有处于非活动状态的设备。 (与我想要的相反)。不幸的是,否定这个查询不会返回我期望的结果。也许我否定错了?这是我的工作:
Date now = new Date();
return
find.where().
.not(Expr.and(
Expr.le("inactivePeriods.start", now),
Expr.ge("inactivePeriods.end", now)
))
.orderBy(sorting + " " + order)
.findPagingList(Global.PAGE_SIZE_DEVICES)
.setFetchAhead(false)
.getPage(page);
谁能给我一个解决方案?或者任何人都可以提出原始 SQL 解决方案吗?
更新
这是生成的 SQL:
[debug] c.j.b.PreparedStatementHandle - select distinct t0.id c0, [...] from device t0 join device_inactive_period u1 on u1.device_id = t0.id where not ((u1.start <= 2016-03-06 11:35:15.048 and u1.end >= 2016-03-06 11:35:15.048 ) ) order by t0.exp_date desc
limit 11
问题是对于每个Device,InactiveDevicePeriod 中可能有 0 到多行,如果 ((u1.start <= 2016-03-06 11:35:15.048 and u1.end >= 2016-03-06 11:35:15.048 ) ),SQL DBMS 会检查每一行。对于每个设备,如果只有 1 行在此条件下返回 true,则将返回整个设备。另一个问题是,如果设备没有InactiveDevicePeriod 条目,则不会返回。
在java中它相当于这种代码的和平(我认为!)(在Device.java中):
public boolean isActive_at_Wrong(Date date){
for (DeviceInactivePeriod inactivePeriod : inactivePeriods) {
if ( (inactivePeriod.start.before(date) || inactivePeriod.start.equals(date)) && inactivePeriod.end.after(date)){
return false;
} else {
return true;
}
}
return false;
}
但我想要的是这个(在 Device.java 中):
public boolean isAactive_at_Correct(Date date){
boolean active = true;
for (DeviceInactivePeriod inactivePeriod : inactivePeriods) {
if ( (inactivePeriod.start.before(date) || inactivePeriod.start.equals(date)) && inactivePeriod.end.after(date)){
active = false;
}
}
return active;
}
【问题讨论】:
-
包括生成的 SQL ...然后查看 where 子句并描述它需要什么,然后将其与您的问题一起发布。
-
我刚刚用更多信息更新了这个问题@RobBygrave
标签: sql playframework playframework-2.3 ebean