Java未将准确的日期存储到mysql数据库

时间:2018-10-31 19:20:28

标签: java mysql jdbc

我正在编写一个程序,将字符串转换为java.util.Date对象,然后将其存储在数据库中,该程序运行正常,没有错误。但是在MySql中,日期存储不正确,java存储的日期是相对于字符串中写入日期的昨天日期。 示例-如果我写“ 2018-11-10”,它将存储“ 2018-11-09”。 我的代码-

import java.sql.Connection;
import java.sql.Date;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class Demo {

    public static void main(String[] args) throws ClassNotFoundException, SQLException {
        Connection con;
        Class.forName("com.mysql.cj.jdbc.Driver");
        Date date = Date.valueOf("2018-11-20"); 
        con = DriverManager.getConnection("jdbc:mysql://localhost:9090/ProjectScheduler", "root", "tiger");
        PreparedStatement prepare = con.prepareStatement("insert into SchedulerDB(Date) values(?)");
        prepare.setDate(1, date);
        prepare.executeUpdate();
    }
}

在MySql工作台中,我创建的表为

create table SchedulerDB(Date date)

当我运行select查询以使用

查看表中的数据时
select * from SchedulerDB

然后在表“ SchedulerDB”中的“日期”列下,我得到了2018-11-19。但是我想要2018-11-20,因为这是我用Java代码编写的内容。请帮助我解决这个问题。

1 个答案:

答案 0 :(得分:2)

tl; dr

myPreparedStatement.setObject(
    … ,
    LocalDate.parse( "2018-11-20")
) ;

详细信息

您正在使用经过精心设计的java.sql.Date类。不幸的是,该类是java.util.Date的子类,尽管文档奇怪地告诉我们忽略该继承事实。因此,尽管java.sql.Date 假装仅表示日期,但实际上是一个时刻,该日期的某天将某个区域的午夜设置为午夜,然后将其调整为UTC。这是一个令人毛骨悚然的设计,并且是从不使用遗留日期时间类的许多原因之一。

对于SQL中的DATE列,请改用现代的LocalDate类。

LocalDate

LocalDate类确实表示仅日期的值,没有时间,也没有time zoneoffset-from-UTC

对于类型类似于SQL标准DATE类型的数据库列,请使用Java中的LocalDate类。

LocalDate ld = LocalDate.parse( "2018-11-20" );

JDBC 4.2

从JDBC 4.2开始,我们可以直接与数据库交换 java.time 对象。

myPreparedStatement.setObject( … , ld ) ;

检索:

LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;

不涉及任何时区,检索到的值将与您存储的2018-11-20相同。

示例应用

这是使用H2 Database Engine的完整示例应用程序。作为一个演示,我将其设置为写入内存数据库,而不是持久存储到实际存储中。

我们用一个具有两列的表创建数据库:

  • 名为pkey_的序号主键
  • 名为DATE的{​​{1}}列

我们插入几个when_对象,然后检索要转储到控制台的行。

LocalDate

运行时。

  

插入LocalDate对象的列表:[2018-11-10,2018-12-31]

     

行pkey_:1时间:2018-11-10

     

行pkey_:2时间:2018-12-31


关于 java.time

java.time框架已内置在Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendarSimpleDateFormat

目前位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解更多信息,请参见Oracle Tutorial。并在Stack Overflow中搜索许多示例和说明。规格为JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要package com.basilbourque.example; import java.sql.*; import java.time.LocalDate; import java.util.List; public class EventDate { public static void main ( String[] args ) { EventDate app = new EventDate(); app.doIt(); } private void doIt ( ) { final String driverName = "org.h2.Driver"; final String catalogName = "event_demo_db"; final String jdbcPath = "jdbc:h2:mem:" + catalogName + ";DB_CLOSE_DELAY=-1"; // Set delay to keep in-memory database even after last connection closed. // Verify JDBC driver. try { Class.forName( driverName ); } catch ( ClassNotFoundException e ) { e.printStackTrace(); } // Connect, and create database. try ( Connection conn = DriverManager.getConnection( jdbcPath ) ; ) { String sql = null; // Create table. try ( Statement stmt = conn.createStatement() ; ) { sql = "CREATE TABLE " + "event_" + " ( \n" + " pkey_ IDENTITY PRIMARY KEY , \n" + " when_ DATE NOT NULL \n" + ") ; \n"; System.out.println( "TRACE - SQL:\n" + sql ); stmt.execute( sql ); } System.out.println( "TRACE - Created table `event_`." ); // Add rows sql = "INSERT INTO event_ ( when_ ) \n" + "VALUES ( ? ) " + "; "; List < LocalDate > dates = List.of( LocalDate.parse( "2018-11-10" ) , LocalDate.parse( "2018-12-31" ) ); System.out.println( "Inserting list of LocalDate objects: " + dates ); try ( PreparedStatement ps = conn.prepareStatement( sql ) ; ) { for ( LocalDate localDate : dates ) { ps.setObject( 1 , localDate ); ps.executeUpdate(); } } // Retrieve rows sql = "SELECT * FROM " + "event_" + " ;"; try ( Statement stmt = conn.createStatement() ; ResultSet rs = stmt.executeQuery( sql ) ; ) { while ( rs.next() ) { int pkey = rs.getInt( "pkey_" ); LocalDate when = rs.getObject( "when_" , LocalDate.class ); System.out.println( "Row pkey_: " + pkey + " when_: " + when ); } } } catch ( SQLException e ) { e.printStackTrace(); } } } 类。

在哪里获取java.time类?

ThreeTen-Extra项目使用其他类扩展了java.time。该项目为将来可能在java.time中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore