Java Spring MySQL 两毫秒之间的字符串时区列

Java Spring MySQL String Timezone column between two milliseconds

我在 MySQL 列 上以字符串形式存储了一个时区日期,格式如下:

2018-07-23T20:54:37.242Z --> start_date

我想要做的是 Between 两毫秒(或日期),如下所示:

SELECT * FROM activity_entity WHERE start_date BETWEEN 1532322000000 AND 1532408399000 

否则,我正在使用 Java Spring 存储库 作为后端,我会像这样发送参数:

Date since = new Date(accessRepPOSTInDto.getSince()); //1532322000000 gives Mon Jul 23 00:00:00 CDT 2018
Date to = new Date(accessRepPOSTInDto.getTo());//1532408399000 gives Mon Jul 23 23:59:59 CDT 2018

@Query(value = "SELECT * FROM activity_entity WHERE start_date BETWEEN :since AND :too , nativeQuery = true)
ActivityEntity findBetweenDates(@Param("since") Date since, @Param("too") Date too);

这样做 returns null;

我以为 MySQL 可以自动格式化两个日期和字符串列来执行 Between,但看起来它不会。

任何帮助将不胜感激。问候。

在您的本机查询中,您需要将 varchar 列的值显式转换为正确的 date/timestamp 以供 between 运算符计算。这就是您的本机查询的样子:

SELECT * FROM activity_entity WHERE STR_TO_DATE(start_date, '%Y-%c-%eT%H:%i:%s.%fZ') BETWEEN :since AND :too

tl;博士

SQL:

SELECT * FROM tbl WHERE event >= ? AND event < ? ;  -- Using Half-Open approach where beginning is *inclusive* while the ending is *exclusive*. 

Java:

myPreparedStatement.setString( 1 , Instant.ofEpochMilli( 1_532_322_000_000L ).toString() ) ;
myPreparedStatement.setString( 2 , Instant.ofEpochMilli( 1_532_408_399_000L ).toString() ) ;

ISO 8601

2018-07-23T20:54:37.242Z

此格式的文本符合 ISO 8601 标准。该标准是将日期时间值表示为文本的最佳方式。但是在数据库中,您应该使用专门构建的数据类型,定义类似于 SQL-标准 TIMESTAMP WITH TIME ZONE 类型的列。搜索 Stack Overflow 了解更多信息。

java.time classes 在 parsing/generating 字符串时默认使用 ISO 8601 格式。因此无需指定格式模式。

Instant instant = Instant.parse( "2018-07-23T20:54:37.242Z" ) ;

从纪元开始计数

您可以使用 Instant class.

转换 UTC 中自 1970 年第一时刻的纪元参考以来的毫秒数
Instant start = Instant.ofEpochMilli( 1_532_322_000_000L ) ;
Instant stop = Instant.ofEpochMilli( 1_532_408_399_000L ) ;

生成数据库列中使用的标准 ISO 8601 格式的字符串。

String startStr = start.toString() ;
String stopStr = stop.toString() ;

避免遗留日期时间 classes

与 Java 的最早版本捆绑在一起的旧日期时间 classes 非常糟糕。永远不要使用它们。它们已被 java.time classes.

完全取代

半开

What I want to do is a Between

SQL 中的 BETWEEN 命令通常 不应 与日期时间值一起使用。该命令是完全“封闭”的,这意味着开头和结尾都是 包含

相反,对于日期时间工作,通常最好将时间跨度定义为半开。在这种方法中,开头是 inclusive,而结尾是 exclusive。例如,从中午到下午 1 点午休时间被开除的学生预计会在时钟敲响 1 点和铃声响起之前 回到座位上。另一个例子,一周从星期一开始,一直到但不包括下一个星期一。

在 SQL 代码中,这意味着查询使用 >=AND<

SELECT *
FROM tbl
WHERE event >= ?
AND event < ?
;

由于带有 Z 的 ISO 8601 格式在按字母顺序排序时是按时间顺序排列的,因此您可以使用 ISO 8601 字符串进行此操作。

myPreparedStatement.setString( 1 , startStr ) ;
myPreparedStatement.setString( 2 , stopStr ) ;

如果您使用了上面讨论的 TIMESTAMP WITH TIME ZONE 列类型,您只需传递 Instant 个对象。

myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , stop ) ;

如果您确实必须使用全封闭方法,请调整查询运算符 >=AND<=。或致电BETWEEN


我不是 Spring 用户,无法为您提供帮助。


关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

您可以直接与数据库交换 java.time 对象。使用 JDBC driver compliant with JDBC 4.2 或更高版本。不需要字符串,不需要 java.sql.* classes.

从哪里获得java.time classes?

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.