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)
)
在自定义 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)"));
如果我像下面这样查询,我们会使用带有 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)
)
在自定义 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)"));