我正在使用ebean的play framework 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
对象作为一个时间段,其中一个设备在INACTIVE中。 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);
返回所有非INACTIVE设备。 (与我想要的相反)。不幸的是,否定此查询不会返回我期望的结果。我是在否定错误吗?这是我的工作:
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到多行,而SQL DBMS会检查每行((u1.start <= 2016-03-06 11:35:15.048 and u1.end >= 2016-03-06 11:35:15.048 ) )
。对于每个设备,如果只有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;
}
答案 0 :(得分:0)
我没有测试过,但我认为您可以使用between
条款:
Date now = new Date();
return find
.where()
.not(Expr.between("inactivePeriods.start", "inactivePeriods.end", now))
.orderBy(sorting + " " + order)
.findPagingList(Global.PAGE_SIZE_DEVICES)
.setFetchAhead(false)
.getPage(page);