如何更新数据库中的日期间隔(Hibernate HQL)

How can I update an interval of dates in the database (Hibernate HQL)

考虑,对于 id id 的某些特定数据库条目,数据库中的日期间隔,从 BEGIN_DATEEND_DATE,表示为 (BEGIN_DATEEND_DATE).

给定两个形成区间 (newBeginDate, newEndDate) 的新日期,我必须更新 (BEGIN_DATE,END_DATE) 以便生成的区间包含所有 4 个日期。换句话说,我想 添加两个间隔 (并且由于我添加它们,结果间隔可能保持不变或增加,但永远不会缩小)。

举几个例子:

如果(BEGIN_DATE,END_DATE) = (January 10,January 20),则:

以下两个查询共同实现了这个目标。第一个更新BEGIN_DATE,第二个更新END_DATE:

session.createQuery(
   "update APPOINTMENTS " +
     "set BEGIN_DATE = :newBeginDate " +
     "where " +
     "(BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) " +
     "and ID = :id ")
           .setParameter("newBeginDate", newBeginDate)
           .setParameter("id", id)
           .executeUpdate();

session.createQuery(
   "update APPOINTMENTS " +
     "set END_DATE = :newEndDate " +
     "where " +
     "(END_DATE is null or END_DATE < :newEndDate) " +
     "and ID = :id ")
        .setParameter("newEndDate", newEndDate)
        .setParameter("id", id)
        .executeUpdate();

我的问题是: 如何在单个查询中完成?

SQL 在涉及更复杂的编程结构时受到限制,因此由于您使用 Hibernate,我将只读取约会实体实例并更新其字段。这将需要两个查询,一个用于读取,一个用于更新,但它仍然只是一个更新语句,并且是最具可读性的解决方案。

如果您仍然只需要一个更新语句而别无其他,可以使用 case 将您的两个语句合并为一个:

update APPOINTMENTS 
set BEGIN_DATE = case when (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate) then :newBeginDate else BEGIN_DATE end,
    END_DATE = case when (END_DATE is null or END_DATE < :newEndDate) then :newEndDate else END_DATE end
where (BEGIN_DATE is null or BEGIN_DATE > :newBeginDate or END_DATE is null or END_DATE < :newEndDate)
    and ID = :id

使用LEAST()GREATEST()函数。对于 NULL,使用 COALESCE().

update APPOINTMENTS
set BEGIN_DATE = coalesce(least(BEGIN_DATE, :newBeginDate), :newBeginDate),
    END_DATE   = coalesce(greatest(END_DATE, :newEndDate), :newEndDate)
where ID = :id

我认为 LEAST 和 GREATEST 不需要解释。如果旧日期为 NULL,COALESCE 将选择新日期。因此,除了 ID = :id 之外,WHERE 子句中不需要任何条件。