Gur*_*rma 5 java hibernate spring-boot
我正在尝试从表中获取特定日期的结果。我使用 URL 以字符串格式传递日期,然后将字符串日期解析为 java.util.Date,然后使用它从表中获取值。在表中,值存储在数据类型为日期时间的列中。
@Query(value = "" +
"FROM " +
" MarketingForm mf " +
"WHERE " +
" (:createdAt is null OR mf.createdAt = :createdAt)" +
" AND (:verticalId is null OR mf.verticalId = :verticalId)" +
" AND (:tag is null OR mf.tag = :tag)"
)
List<MarketingForm> findAllByCreatedAtAndVerticalIdAndTag(@Param("createdAt") Date createdAt, @Param("verticalId") Long verticalId, @Param("tag") String tag);
Run Code Online (Sandbox Code Playgroud)
下面是字符串日期和相应的 java.util.Date
我用来将字符串日期解析为 java.util.Date 的方法 -
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
return formatter.parse(formCreatedDate);
Run Code Online (Sandbox Code Playgroud)
现在我不确定这里发生了什么。java.util.Date 没有被正确解析,或者我是否在做不正确的比较,但即使记录在表中,查询也无法获取结果。
为什么即使表中存在记录,上述 SQL 也无法获取指定日期的记录?
注意:表中的数据是时间格式,我只需要比较日期的日期分量即可。
由于您的问题不清楚,我不确定您的确切期望,因此我无法给出准确的答案。但是我可以讨论您的方法和代码中的一些问题。
首先,永远不要使用java.util.Date. 这个可怕的类是旧日期时间类的一部分,这些类在多年前被JSR 310 中定义的现代java.time类所取代。同样,永远不要使用,也永远不要使用。Sun、Oracle和JCP社区在采用 JSR 310 后放弃了这些遗留类,您也应该如此。JPA和Hibernate都已更新以支持java.time类,就像JDBC 4.2规范一样。CalendarSimpleDateFormat
另一个可能的问题,也许您正在java.sql.Date与java.util.Date. 小心你import在那里的陈述。而且,再一次,永远不要使用任何一个Date类。
你提到了一串2021-03-03,但并没有真正解释它在哪里。无论如何,这代表一个仅限日期的值。但是你说你访问了DATETIMEMySQL 中的一列。根据MySQL 8 文档,该类型表示带有时间的日期。
DATETIME 类型用于同时包含日期和时间部分的值。MySQL 以 'YYYY-MM-DD hh:mm:ss' 格式检索和显示 DATETIME 值。支持的范围是“1000-01-01 00:00:00”到“9999-12-31 23:59:59”。
因此,通过仅日期值查询日期时间列是没有意义的。数据库无法将仅日期值与带时间日期的值进行比较。您需要为您的开始和结束指定一个时间跨度,一对带有时间的日期值。
另一个问题:您正在尝试使用java.util.Datewhich 代表一个时刻,在 UTC 上下文中看到的带有时间的特定日期 - 但DATETIMEMySQL 中的类型是一种不同的动物。DATETIMEMySQL 中的类型表示具有时间的日期,但缺少偏移量或时区的上下文。这种类型类似于 SQL 类型TIMESTAMP WITHOUT TIME ZONE。
当心:如果您试图表示数据库中的时刻、时间线上的特定点,那么您的列使用了错误的数据类型。暂时,您必须使用类似于 SQL 标准的数据类型TIMESTAMP WITH TIME ZONE。在 MySQL 8 中,这就是TIMESTAMP类型。TIMESTAMPMySQL 中的类型跟踪在 UTC 中看到的时刻,总是在 UTC 中。如果您有问题的列是名为 的列createdAt,那么您几乎肯定使用了错误的数据类型,因为必须使用 SQL-standard 来跟踪作为历史记录传递的时刻TIMESTAMP WITH TIME ZONE。但是我将忽略这个关键问题,并继续处理您在问题中指定的书面类型。
如果您不跟踪时刻,例如跟踪保存在附加列中的时区旁边的未来约会,那么您的使用DATETIME将是正确的。如果您确定此数据类型适合您的目的,那么在 Java 中适当的匹配将是LocalDateTime类。
DATETIME通过使用半开放方法来定义时间跨度,对列上一天的数据进行查询。开始是包容性的,而结束是排斥性的。因此,一天从一天的第一时刻开始,一直到(但不包括)第二天的开始。对于半开,我们不使用 SQL 关键字BETWEEN。
这是一个简单的代码示例以适应您的情况。我既不使用 Spring 也不使用 Hibernate,因此您必须相应地进行翻译。
对于仅限日期的输入字符串,解析为LocalDate.
提示:询问“大于或等于”的简短方法是“不小于”。我们在下面的 SELECT 语句中的谓词的第一种情况下看到了这一点。
LocalDate ld = LocalDate.parse( "2021-03-03" ) ;
LocalDateTime startOfDay = ld.atStartOfDay() ;
LocalDateTime startOfNextDay = ld.plusDays( 1 ).atStartOfDay() ;
String sql = "SELECT * FROM my_table WHERE when !< ? AND when < ? ;" ; // Performing query over a span-of-time defined as Half-Open.
…
myPreparedStatement.setObject( 1 , startOfDay ) ;
myPreparedStatement.setObject( 2 , startOfNextDay ) ;
Run Code Online (Sandbox Code Playgroud)
检索DATETIME值。
LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;
Run Code Online (Sandbox Code Playgroud)
所有这些已经在 Stack Overflow 上讨论过很多次了。搜索以了解更多信息。
| 归档时间: |
|
| 查看次数: |
136 次 |
| 最近记录: |