postgres jpql中的日期添加

Date addition in postgres jpql

如果我像下面这样查询,我们会使用带有 jpql 的 oracle db 获取数据。

public static void main(String[] args) {
    EntityManagerFactory emf = Persistence.createEntityManagerFactory("postgres");
    EntityManager entityManager = emf.createEntityManager();
    try {
        entityManager.getTransaction().begin();
        String jpqlQuery = "SELECT coalesce(c.actualDateTime, "
                + "coalesce("
                + "c.propDepDateTime+"
                + "TO_NUMBER(c.estOnDateTime-c.estOffDateTime),"
                + "c.estOnDateTime )) FROM Flight c  ";
        
        Query query = entityManager.createQuery(jpqlQuery);
        List<Object> objects = query.getResultList();

        objects.stream().forEach((x) -> System.out.println(x));
        entityManager.getTransaction().commit();

    } finally {

        entityManager.close();
        emf.close();
    }
}
import org.springframework.format.annotation.DateTimeFormat;
@Entity
@Table(name = "FLIGHT")
public class Flight {

    @Id
    private Long id;

    @Column(name = "ACT_DATETIME", columnDefinition = "Date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date actualDateTime;

    @Column(name = "PROPAG_DEP_DATETIME", columnDefinition = "Date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date propDepDateTime;

    @Column(name = "EST_ON_DATETIME", columnDefinition = "Date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date estOnDateTime;

    @Column(name = "EST_OFF_DATETIME", columnDefinition = "Date")
    @Temporal(TemporalType.TIMESTAMP)
    @DateTimeFormat(style = "M-")
    private Date estOffDateTime;
DROP TABLE IF EXISTS flight;

CREATE TABLE flight(
id BIGINT PRIMARY KEY , 
ACT_DATETIME TIMESTAMP WITHOUT TIME ZONE,
PROPAG_DEP_DATETIME TIMESTAMP WITHOUT TIME ZONE,
EST_ON_DATETIME TIMESTAMP WITHOUT TIME ZONE,
EST_OFF_DATETIME TIMESTAMP WITHOUT TIME ZONE
);

INSERT INTO flight(ID,ACT_DATETIME, PROPAG_DEP_DATETIME,EST_ON_DATETIME,EST_OFF_DATETIME)
VALUES(
    1,(SELECT now()::timestamp),(SELECT now()::timestamp+1 * INTERVAL '1 DAY'),(SELECT now()::timestamp+2* INTERVAL '1 DAY'),
    (SELECT now()::timestamp+3* INTERVAL '1 DAY')
);

在迁移到 Postgres 时,我如下更改了 jpql,但抛出了错误:

operator does not exist: timestamp without time zone + numeric
  Hint: No operator matches the given name and argument types. You might need to add explicit type casts.

尝试乘以间隔等,但尚未奏效。欢迎任何帮助。

String jpqlQuery = "SELECT coalesce(c.actualDateTime, "
                    + "coalesce("
                    + "c.propDepDateTime+("
                    + "TO_NUMBER(quote_literal(c.estOnDateTime-c.estOffDateTime),'99999999.99999999')),"
                    + "c.estOnDateTime )) FROM Flight c  ";

如果从另一个时间戳中减去一个时间戳,您得到的是 interval 而不是数字,因此将 c.estOnDateTime-c.estOffDateTime 的结果传递给 to_number() 也会导致错误。然后您尝试将该数字(开头无效)添加到 timestamp,这也是不允许的。

在这种情况下使用 quote_literal() 毫无意义。

但是您可以向时间戳添加一个时间间隔,据我所知,以下内容应该可以满足您的要求:

coalesce(c.actualDateTime, 
         coalesce(c.propDepDateTime + (c.estOnDateTime-c.estOffDateTime),               
                  c.estOnDateTime) 
         ) 

Online example

在自定义 PostgreDialect 的自定义函数下方编写并注册 & 将 postgres jpql 查询中的 (c.actualDateTime-c.propDepDateTime) 更改为 to_interval(c.actualDateTime-c.propDepDateTime) 解决了此问题。谢谢 https://whosebug.com/users/330315/a-horse-with-no-name|

registerFunction("to_interval", new SQLFunctionTemplate(StandardBasicTypes.TIMESTAMP, "cast(?1 as interval)"));