将时间戳从 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));
这很有效。希望对大家有所帮助!
我正在创建一个与 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));
这很有效。希望对大家有所帮助!