2016-03-05 44 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