当Postgresql中的参数为“无时区的时间戳”时,Java中的参数类型应该是什么?

问题描述 投票:5回答:2

我正在尝试通过Java和JDBC在PostgreSQL中运行查询。

postgresql中“表”的“活动日期”列为“无时区的时间戳”。我尝试使用String传递日期,但没有成功(org.postgresql.util.PSQLException:错误:运算符不存在:没有时区的时间戳>字符变化)

我应该使用什么类型而不是String来存储“开始日期”和“结束日期”并将它们传递给查询?

BTW SELECT COUNT(*) FROM table WHERE activitydate > '2014-11-20' AND activitydate < '2014-11-21' AND zipcode = 12345在pgadmin中完美运行。

public Response query(
          @QueryParam("start_date") String start_date,
          @QueryParam("end_date") String end_date,
          @QueryParam("zipcode") String zipcode
          ) throws Exception {
...
...

pstmt = conn.prepareStatement("SELECT COUNT(*) FROM table WHERE activitydate > ? AND activitydate < ? AND zipcode = ?");

pstmt.setString(1, start_date); 
pstmt.setString(2, end_date); 
pstmt.setString(3, zipcode); 

更新:我将其更改为java.sql.Timestamp,但仍然无法正常工作:

public Response query(
          @QueryParam("start_date") Timestamp start_date,
          @QueryParam("end_date") Timestamp end_date,
          @QueryParam("zipcode") String zipcode
          ) throws Exception {
...
...

pstmt = conn.prepareStatement("SELECT COUNT(*) FROM table WHERE activitydate > ? AND activitydate < ? AND zipcode = ?");

pstmt.setTimestamp(1, start_date); 
pstmt.setTimestamp(2, end_date); 
pstmt.setString(3, zipcode);
java postgresql jdbc
2个回答
3
投票

您必须使用java.sql.Timestampjava.sql.Date


0
投票

tl; dr

对于使用半开时间跨度的SQL:"SELECT * FROM tbl WHERE when !< ? AND when < ? ; "

myPreparedStatement.setObject(       // Use a prepared statement so you can pass smart objects rather than dumb strings.
    1 ,                              // Specify which placeholder is being fulfilled.
    LocalDate                        // Represent a date-only value, without time-of-day and without time zone or offset-from-UTC.
    .parse( "2014-11-20" )           // Parse an input string in standard ISO 8601 format to get a `LocalDate` object.
    .atStartOfDay()                  // Determine the first moment of the day on that date. Returns a `LocalDateTime` object representing a date with time-of-day but lacking any concept of time zone or offset-from-UTC.
) ;
myPreparedStatement.setObject( 
    2 , 
    LocalDate
    .parse( "2014-11-21" )
    .atStartOfDay()
) ;

注意:我猜您在数据库中使用的列类型错误。 仅可使用TIMESTAMP WITH TIME ZONE不是 TIMESTAMP WITHOUT TIME ZONE来跟踪时刻。搜索堆栈溢出以获取更多信息。

不是片刻

Jens的答案现在已过时。如今,您应该使用现代的[[java.time类,该类取代了麻烦的旧传统日期时间类。

postgresql中的“无时区的时间戳”?

Postgres和SQL标准上的此数据类型故意缺少从UTC偏移或时区的上下文。因此,请注意,这种类型不能表示时刻,是时间线上的一个点。

我将其更改为java.sql.Timestamp

不是,数据类型错误。 java.sql.Timestamp类不但具有传统意义,而且在设计上存在严重缺陷,它代表时刻,是时间轴上的特定点。因此,这与您的TIMESTAMP WITHOUT TIME ZONE类型的列不匹配。

LocalDateTime

您应该改用LocalDateTime类。此类表示带有日期的日期,但缺少任何偏移或时区的概念。

要从数据库中检索值。

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

将值发送到数据库。

myPreparedStatement.setObject( … , ldt ) ;

一天的开始

从表WHERE活动日期>'2014-11-20'和活动日期
您在这里还有另一个不匹配之处。您提供的是仅日期的值,但是您的列中包含日期与时间的值。

另一个问题:您在应使用智能对象的地方使用了哑字符串。从JDBC 4.2开始,我们可以与数据库交换

java.time

对象。使用带占位符的PreparedStatement,并通过`set >>传递对象

Table of date-time types in Java (both legacy and modern) and in standard SQL要解决日期中的时间问题,我们需要确定一天的开始时间。使用LocalDateTime,我们无需考虑时区异常。因此,一天总是从00:00开始。但是,我们应该养成要求

java.time

确定一天中开始时间的习惯。

LocalDate startDate = LocalDate.parse( "2014-11-20" ) ; LocalDate stopDate = LocalDate.parse( "2014-11-21" ) ; LocalDateTime start = startDate.atStartOfDay() ; LocalDateTime stop = stopDate.atStartOfDay() ; 用占位符为您编写SQL。

我建议您改变思维方式,以习惯于定义时间跨度的半开放式方法。在Half-Open中,开头为

inclusive

,而结尾为

exclusive

。因此,对于20日的一整天,请搜索等于或晚于20日的日期,直到(包括)21日为止。至于第一部分,说“等于或晚于”等于“不早于”,因此我们使用!<String sql = "SELECT * FROM tbl WHERE when !< ? AND when < ? ; " ; sql字符串输入到准备好的语句中。然后将两个LocalDateTime对象传递给占位符。myPreparedStatement.setObject( 1 , start ) ; myPreparedStatement.setObject( 2 , stop ) ;
© www.soinside.com 2019 - 2024. All rights reserved.