2016-03-05 51 views
0

我正在使用ebean的play framework 2.3.4。我有这2代表在我的数据库:否定ebean中的表达

@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对象作为一个时间段,在该设备中的非活动。 A 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); 

确切返回所有非活动的设备。 (与我想要的相反)。不幸的否定这个查询不会返回我期望的结果。 mayble我否认错误?这是我做什么:

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解决方案

UPDATE

这里是生成的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可以有0到许多线路中的InactiveDevicePeriod和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

包含生成的SQL ...然后LOO k在where子句中,并描述它需要的内容,然后用你的问题发布。 –

+0

我刚更新了更多的信息@RobBygrave – behzad

回答

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); 
+0

谢谢,但它仍然不会返回我想要的。 :-( – behzad

+0

什么是在这种情况下返回? – marcospereira

+0

我有4个示例设备,其中2个当前是活动的,其他2当前是非活动的,你的代码返回活动中的一个和活动中的一个。不会返回,具有以下'DeviceInactivePeriod'对象:1)start:9.2.2016 end:1.3.2016 2)start:3.3.2016 end:6.3.2016 – behzad