将时间戳从 Java 应用程序插入 MySQL

Inserting Timestamp into MySQL from Java application

我正在创建一个与 MySQL 数据库通信的 Java 应用程序。使用 XAMPP 5.6.33-0 和 phpMyAdmin。我有以下方法,在其他值中,将时间戳插入 table RATING:

PreparedStatement pst = myConn.prepareStatement("INSERT INTO RATING  
       (ratingDate) VALUES(?)");
        java.util.Date today = new java.util.Date();
        Timestamp ts = new java.sql.Timestamp(today.getTime());
        pst.setTimestamp(1, ts);
        pst.executeUpdate();

RATING 关系的架构如下所示:

CREATE TABLE RATING
(cID INT,
 rID INT,
 stars INT,
 ratingDate TIMESTAMP,
 FOREIGN KEY(cID) REFERENCES CUSTOMER(cID) on delete cascade,
 FOREIGN KEY(rID) REFERENCES ROOM(rID)
 ) ;

因此属性 ratingDate 被定义为时间戳。一切正常,除了插入时间戳时,其值始终设置为全零:0000-00-00 00:00:00

我尝试使用 t.toString 将时间戳转换为字符串,可以清楚地看到时间戳对象已正确创建。看来问题出在 setTimestamp() 方法上。此外,将 ratingDate 的数据类型转换为 Date 并使用 setDate() 方法工作正常,但 setTimestamp() 函数始终将属性值设置为全零。

当然,有解决方法。我可以将日期声明为 varchar,将 Timestamp 转换为 String 并使用 setString() 插入它,但我真的很想知道问题出在哪里。 运行 Eclipse 与 Tomcat 服务器。控制台中没有错误。

提前感谢您的帮助,我很乐意提供任何其他必要的信息。

避免遗留日期时间类

全零值是个谜。但我可以告诉你,你使用的是可怕的日期时间 类,几年前随着 JSR 的采用,java.time 类 取代了它310. 这使您的工作变得比需要的更复杂。

我建议创建一个简单的虚拟对象 table 来缩小您的问题范围。

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
myPreparedStatement.setObject( … , odt ) ;

检索。

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime ) ;

示例应用程序

我不使用 MySQL。但这是一个使用 H2 Database Engine.

的完整示例应用程序
package work.basil.example;


import org.h2.jdbcx.JdbcDataSource;

import java.sql.*;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

public class H2DateTimeExample
{
    public static void main ( String[] args )
    {
        H2DateTimeExample app = new H2DateTimeExample ();
        app.demo ();
    }

    private void demo ( )
    {
        JdbcDataSource dataSource = new JdbcDataSource ();
        dataSource.setURL ( "jdbc:h2:mem:offsetdatetime_example_db;DB_CLOSE_DELAY=-1" ); // Set `DB_CLOSE_DELAY` to `-1` to keep in-memory database in existence after connection closes.
        dataSource.setUser ( "scott" );
        dataSource.setPassword ( "tiger" );

        // Create table.
        String sql = "CREATE TABLE person_ ( \n" +
                " pkey_ UUID NOT NULL DEFAULT RANDOM_UUID() PRIMARY KEY , \n" +
                " name_ VARCHAR NOT NULL , \n" +
                "first_contacted_ TIMESTAMP WITH TIME ZONE NOT NULL " +
                ") ;";
//            System.out.println ( sql );
        try (
                Connection conn = dataSource.getConnection () ;
                Statement stmt = conn.createStatement () ;
        )
        {
            stmt.execute ( sql );
        } catch ( SQLException e )
        {
            e.printStackTrace ();
        }

        // Insert row.
        sql = "INSERT INTO person_ ( name_ , first_contacted_ ) \n";
        sql += "VALUES ( ? , ? ) \n";
        sql += ";";
        try (
                Connection conn = dataSource.getConnection () ;
                PreparedStatement pstmt = conn.prepareStatement ( sql , Statement.RETURN_GENERATED_KEYS ) ;
        )
        {
            OffsetDateTime odt = OffsetDateTime.now ( ZoneOffset.UTC );

            pstmt.setString ( 1 , "Jesse Johnson" );
            pstmt.setObject ( 2 , odt );
            pstmt.executeUpdate ();

            ResultSet rs = pstmt.getGeneratedKeys ();
//            System.out.println( "INFO - Reporting generated keys." );
//            while ( rs.next() ) {
//                UUID uuid = rs.getObject( 1 , UUID.class );
//                System.out.println( "generated keys: " + uuid );
//            }

        } catch ( SQLException e )
        {
            e.printStackTrace ();
        }


        // Query table.
        sql = "TABLE person_ ;";
        try (
                Connection conn = dataSource.getConnection () ;
                PreparedStatement pstmt = conn.prepareStatement ( sql ) ;
        )
        {
            try ( ResultSet rs = pstmt.executeQuery () ; )
            {
                while ( rs.next () )
                {
                    UUID pkey = rs.getObject ( "pkey_" , UUID.class );
                    String name = rs.getString ( "name_" );
                    OffsetDateTime firstContacted = rs.getObject ( "first_contacted_" , OffsetDateTime.class );
                    System.out.println ( "pkey: " + pkey + " | name: " + name + " | firstContacted: " + firstContacted );
                }
            }

        } catch ( SQLException e )
        {
            e.printStackTrace ();
        }

        System.out.println ( "Done." );

    }
}

当运行.

pkey: b14fd25f-1598-4f09-9475-83ac5967a338 | name: Jesse Johnson | firstContacted: 2019-07-28T02:10:07.731005Z

Done.

经过一些额外的研究,我明白了。问题是 java Timestamp 对象在末尾使用毫秒,而 MySQL table 中的时间戳属性没有(格式为“yyyy-MM-dd HH:mm:ss").因此,这种不匹配阻止了正确时间戳的插入,而是将一个全为零的元组放入 MySQL table 中。解决方法是在java代码中格式化Timestamp对象,将毫秒截掉,然后将Timestamp对象插入MySQL table:

java.util.Date today = new java.util.Date();
java.sql.Timestamp timestamp = new java.sql.Timestamp(today.getTime());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); 
pst.setObject(4, formatter.format(timestamp)); 

这很有效。希望对大家有所帮助!