否定ebean中的表达

时间:2016-03-05 10:31:56

标签: sql playframework playframework-2.3 ebean

我正在使用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

问题是,对于每个DeviceInactiveDevicePeriod中可能有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;
}

1 个答案:

答案 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);