Я использую play framework 2.3.4 с ebean. У меня есть эти 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 до многих строк в SQL СУБД InactiveDevicePeriod
и проверяет каждую строку, если ((u1.start <= 2016-03-06 11:35:15.048 and u1.end >= 2016-03-06 11:35:15.048))
, для каждого устройства, если существует только одна строка, которая возвращает 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 ... а потом Лоо k в предложении where и описать, что это должно быть, затем опубликуйте это с вашим вопросом. –
Я только что обновил вопрос с дополнительной информацией @RobBygrave – behzad