将 java.sql.Timestamp 与 DB2 时间戳相匹配

问题描述 投票:0回答:1

我需要将时间戳值作为 URL 中的参数传递以检索一些数据。 DB2中时间戳的格式为:2022-05-25-11:10:44.662000,但在java.sql.Timestamp中为:2022-05-25 11:10:44.0 当我通过它时,它返回空列表。

我的ActionController类方法:

@GetMapping(value = "/fetchData/{id}/{timestamp}")
  def fetchData(@PathVariable int id, @PathVariable Timestamp timestamp) {
    def serviceResult = actionService.fetchData(id, timestamp);
    return parseServiceResult(serviceResult)
  }

我的ActionService类方法:

  ServiceResult fetchData(int id, Timestamp timestamp) {
    ServiceResult ret = new ServiceResult()
    List<DataDTO> retSet = new ArrayList<DataDTO>()
    List<String> errorMessage = new ArrayList<String>()
    try {
      retSet = actionEntity.fetchData(id, timestamp)
    } catch (CollectionsException e) {
      errorMessage << "ActionService.fetchData error"
      log.debug("ActionService.fetchData error" + e.getMessage())
    }
    ret = new ServiceResult(success: errorMessage.isEmpty(), result: retSet, errorMessageTextList: errorMessage)

    ret
  }

我的ActionEntity类方法:

ArrayList<DataDTO> fetchPoulsFromStorno(int id, Timestamp timestamp) throws CollectionsException {

    def sql = """SELECT * FROM NSNP.TABLE1 PT INNER JOIN NSNP.TABLE2 ST
                        ON (ST.COLUMN1 = PT.COLUMN1 AND
                        ST.COLUMN2 = PT.COLUMN2 AND
                        ST.COLUMN3 = PT.COLUMN3 AND
                        ST.COLUMN4 = PT.COLUMN4 AND
                        ST.COLUMN5 = PT.COLUMN5 AND
                        ST.COLUMN6 = PT.COLUMN6 AND
                        ST.COLUMN7 = PT.COLUMN7 AND
                        ST.COLUMN8 = PT.COLUMN8 )
                        WHERE ST.ID = $id AND ST.TIMESTAMP= $timestamp"""


    ArrayList<DataDTO> dataList = new ArrayList<DataDTO>()

    try {
      if (this.sql != null) {
        this.sql.eachRow(sql) {
          resultSet ->
            System.out.println(resultSet)
            DataDTO dataDTO = new DataDTO()
            dataDTO .setProperty1(resultSet.COLUMN1)
            dataDTO .setPropety2(resultSet.COLUMN2)
            dataDTO .setProperty3(resultSet.COLUMN3)
            
            dataList.add(dataDTO)
        }
      }
    } catch (SQLException se) {
      log.info "ActionEntity.fetchData error $se.message  executed sql: $sql"
    } finally {
      if (this.sql != null) {
        this.sql.close()
      }
    }
    dataList
  }

无法为您提供准确和真实的数据,但我相信您会理解代码以及我想要做什么。

java sql groovy timestamp db2
1个回答
3
投票

tl;博士

您使用了错误的类型。

  • 要与
    TIMESTAMP WITHOUT TIME ZONE
    类型的 DB2 列交换数据,请使用
    java.time.LocalDateTime
  • 要与
    TIMESTAMP WITH TIME ZONE
    类型的 DB2 列交换数据,请使用
    java.time.OffsetDateTime

永远不要使用有缺陷的遗留类

java.sql.Timestamp

👉 您的小时差异可能是由于该类针对时区进行调整而导致的,这是有问题的,因为 DB2 中的

TIMESTAMP
列(
TIMESTAMP WITHOUT TIME ZONE
列)没有时区或偏移量。

详情

DB2 中时间戳的格式为:2022-05-25-11:10:44.662000

不,DB2 中的

TIMESTAMP
类型没有“格式”。文本有格式。但该类型
TIMESTAMP
不包含文本。该类型使用其自己的内部定义的数据来跟踪日期时间值。

Java 中

TIMESTAMP WITHOUT TIME ZONE
类型的 DB2 列的匹配类型是
java.time.LocalDateTime

但是在 java.sql.Timestamp 中

切勿使用

Timestamp
类。该类是遗留日期时间类的一部分,这些类在设计上存在严重缺陷。它们几年前就被 JSR 310 中定义的现代 java.time 类所取代。
Timestamp
类专门被
java.time.Instant
所取代,不过为了与数据库交互,您可以使用
OffsetDateTime
类。

JDBC 4.2 及更高版本要求所有 JDBC 驱动程序支持 java.time 类的适当子集。

瞬间与非瞬间

另一个问题是 DB2 中的

TIMESTAMP
TIMESTAMP WITHOUT TIME ZONE
的缩写)故意缺少与 UTC 或时区偏移的上下文。如果没有偏移量或区域,该类型就不能用于表示时刻、时间轴上的特定点。

相比之下,

java.sql.Timestamp
does代表一个时刻,时间轴上的一个特定点。

所以 DB2 中的

TIMESTAMP
java.sql.Timestamp
不匹配。

👉 相反,要与 DB2 中的

TIMESTAMP
列交换值,请使用
java.time.LocalDateTime
类。与 DB2 类型一样,该类故意缺少偏移量或区域的上下文。

LocalDateTime ldt = LocalDateTime.parse( "2022-05-25T11:10:44.662000" ) ;

查看此代码在 Ideone.com 上实时运行

ldt.toString() 是 2022-05-25T11:10:44.662

写作。

myPreparedStatement.setObject( … , ldt ) ;

检索。

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

分辨率

DB2 中的

TIMESTAMP
类型解析为非常精细的皮秒分辨率。引用手册:

小数秒部分的位数使用 0 - 12 范围内的属性指定,默认值为 6

A 纳秒,十亿分之一秒,是九位数字的小数秒。十二位数字代表皮秒,万亿分之一秒。

java.time类的分辨率为纳秒。

© www.soinside.com 2019 - 2024. All rights reserved.