我正在编写一个程序,将字符串转换为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代码编写的内容。请帮助我解决这个问题。
答案 0 :(得分:2)
myPreparedStatement.setObject(
… ,
LocalDate.parse( "2018-11-20")
) ;
您正在使用经过精心设计的java.sql.Date
类。不幸的是,该类是java.util.Date
的子类,尽管文档奇怪地告诉我们忽略该继承事实。因此,尽管java.sql.Date
假装仅表示日期,但实际上是一个时刻,该日期的某天将某个区域的午夜设置为午夜,然后将其调整为UTC。这是一个令人毛骨悚然的设计,并且是从不使用遗留日期时间类的许多原因之一。
对于SQL中的DATE
列,请改用现代的LocalDate
类。
LocalDate
LocalDate
类确实表示仅日期的值,没有时间,也没有time zone或offset-from-UTC。
对于类型类似于SQL标准DATE
类型的数据库列,请使用Java中的LocalDate
类。
LocalDate ld = LocalDate.parse( "2018-11-20" );
从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 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.Date
,Calendar
和SimpleDateFormat
。
目前位于Joda-Time的maintenance 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中添加内容提供了一个试验场。您可能会在这里找到一些有用的类,例如Interval
,YearWeek
,YearQuarter
和more。