我知道java.sql.Date应该将小时,分钟,秒和毫秒设置为零,以符合标准sql日期的定义.这记录在here(Java 8中相同).
我也知道Oracle DATE type确实有YEAR,MONTH,DAY,HOUR,MINUTE和SECOND这些时间字段.但没有分数秒和时区.
我注意到Java 6和Java 8中的相同查询行为不一样:
private static final String REQUETE_LISTE_CALENDRIER_DATE =
" SELECT ID_DATE,JOUR" +
" FROM CALENDRIER " +
" WHERE ID_DATE = ? ";
绑定到PreparedStatement
的java.sql.Date“dateCourante”定义如下(它将值设置为那些时间字段):
GregorianCalendar gregorianCalendar = new GregorianCalendar(); // "now"
java.sql.Date dateCourante = new java.sql.Date(gregorianCalendar.getTime().getTime()); // date AND time of "now"
>使用Java 6,我找到了一个值,
>使用Java 8,我没有.
在我的数据库中,日期的小时,分钟,秒为零.我们可以查看以下查询:
select to_char(id_date,'DD/MM/YYYY HH24:MI:SS')
from calendrier
where id_date = to_date('26/08/2016','DD/MM/YYYY');
这给了:
26/08/2016 00:00:00
所以,我的理解是:
>在Java 6中,在数据库上启动查询之前,java.sql.Date
的时间字段设置为零
>在Java 8中,java.sql.Date
的时间字段保留在查询中.
我无法找到有关此行为的文档.
任何人都可以确认或解释吗?
作为解决方法,我使用它,如here所述:
dDate = java.sql.Date.valueOf(dDate.toLocalDate()); //其中dDate是java.sql.Date
java.sql.Date是仅限日期的
您在Java端选择了错误的类.虽然java.sql.Date
类确实在其内部设置了UTC中00:00:00的时间,但您应该忽略该事实,如类文档所指示的那样. java.sql.Date用于仅限日期的值,没有时间和没有时区.
这个类是一个糟糕的设计,一个糟糕的黑客,继承自java.util.Date,同时告诉你忽略该继承事实.
java.sql.Timestamp是日期和时间
java.sql.Timestamp
是您需要的类型而不是java.sql.Date
.(但请继续阅读以获得更好的课程.)
从最早的Java版本开始,一大堆旧的日期时间类是一个勇敢的行业首次尝试解决日期时间处理问题,但它们不足.它们的设计很糟糕,令人困惑,也很麻烦.避免它们:java.util.Date,java.util.Calendar,java.util.GregorianCalendar,java.text.DateFormat,java.text.SimpleDateFormat.如果可能的话,也要避免使用java.sql类型.而是使用java.time类.
JDBC 4.2
从JDBC 4.2开始,您的JDBC驱动程序可能能够直接从您的数据库访问java.time类型. PreparedStatement :: setObject和ResultSet :: getObject方法可能能够将数据库中的日期时间值作为java.time对象呈现.
Instant instant = myResultSet.getObject( 1 );
…也许…
Instant instant = myResultSet.getObject( 1,Instant.class );
如果您的驱动程序不那么强大,那么请简单地转换为java.sql类型并立即转换为java.time.使用java.time完成所有业务逻辑.仅适用于与数据库交换数据的java.sql类型.要转换为/从java.time,请查找添加到旧类的新方法.例如,java.sql.Timestamp::toInstant
.
这里我们从ResultSet中提取java.sql.Timestamp并立即将其转换为Instant.您可能希望在两行而不是一条组合行上执行此操作以进行调试.
Instant instant = myResultSet.getTimestamp( 1 ).toInstant();