Of course! Working with DATETIME in Java and MySQL is a very common task. The key is to handle the conversion between Java's java.util.Date / java.time objects and MySQL's DATETIME string format ('YYYY-MM-DD HH:MM:SS') correctly.

Here’s a comprehensive guide covering the best practices, common pitfalls, and code examples.
Understanding the Data Types
First, let's clarify the types involved:
-
MySQL
DATETIME: This data type stores a date and time value in the format'YYYY-MM-DD HH:MM:SS'. It can store values from'1000-01-01 00:00:00'to'9999-12-31 23:59:59'. It's precise to the second. -
Java
java.util.Date(Legacy): An older class that represents a single point in time, including both date and time. It's tied to milliseconds since the "epoch" (January 1, 1970, 00:00:00 GMT). It is not recommended for new code.
(图片来源网络,侵删) -
Java
java.time(Modern - Java 8+): This is the modern, preferred API for date and time in Java. The most relevant classes forDATETIMEare:java.time.LocalDateTime: Represents a date and time, but without a time zone. This is the best match for MySQL'sDATETIMEtype, asDATETIMEis also time-zone naive.java.time.ZonedDateTime: Represents a date and time with a specific time zone. Use this if your data is tied to a specific location (e.g., "New York time").java.time.Instant: Represents a point on the timeline in UTC. Useful for data exchange and database storage, but requires conversion to display.
The Best Practice: Using java.time.LocalDateTime
Since DATETIME is time-zone naive, LocalDateTime is the most logical and type-safe Java object to use for it.
Step 1: Database Table Setup
Let's assume you have a table like this:
CREATE TABLE events (
id INT AUTO_INCREMENT PRIMARY KEY,
event_name VARCHAR(255),
event_time DATETIME -- This is our column of interest
);
Step 2: Java Code (using JDBC and java.time)
You need to use PreparedStatement for safe and efficient database operations.

Inserting a DATETIME into MySQL
You can use setObject() with a LocalDateTime object, and the JDBC driver will handle the conversion to the correct string format.
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.time.LocalDateTime;
public class MysqlDateTimeExample {
private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void main(String[] args) {
// 1. Create a LocalDateTime object (e.g., current time)
LocalDateTime now = LocalDateTime.now();
// 2. The SQL INSERT statement with a placeholder (?)
String sql = "INSERT INTO events (event_name, event_time) VALUES (?, ?)";
// Use try-with-resources to automatically close the connection
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
// 3. Set the parameters for the prepared statement
pstmt.setString(1, "Java Conference");
pstmt.setObject(2, now); // setObject handles the LocalDateTime to DATETIME conversion
// 4. Execute the update
int rowsAffected = pstmt.executeUpdate();
System.out.println(rowsAffected + " row inserted successfully!");
System.out.println("Inserted time: " + now);
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Retrieving a DATETIME from MySQL
When you retrieve a DATETIME column, you can get it as a java.sql.Timestamp (a subclass of java.util.Date) or, even better, directly as a LocalDateTime using getObject().
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDateTime;
public class MysqlDateTimeSelectExample {
private static final String DB_URL = "jdbc:mysql://localhost:3306/your_database";
private static final String USER = "your_username";
private static final String PASS = "your_password";
public static void main(String[] args) {
String sql = "SELECT id, event_name, event_time FROM events WHERE id = ?";
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setInt(1, 1); // Let's fetch the first record we inserted
try (ResultSet rs = pstmt.executeQuery()) {
if (rs.next()) {
// --- Method 1: Modern way (Recommended) ---
// Get the DATETIME column as a LocalDateTime object
LocalDateTime eventTime = rs.getObject("event_time", LocalDateTime.class);
System.out.println("Retrieved time (LocalDateTime): " + eventTime);
// --- Method 2: Legacy way (Not recommended for new code) ---
// Get the DATETIME column as a java.sql.Timestamp
// java.sql.Timestamp timestamp = rs.getTimestamp("event_time");
// System.out.println("Retrieved time (Timestamp): " + timestamp);
// LocalDateTime fromTimestamp = timestamp.toLocalDateTime();
// System.out.println("Converted to LocalDateTime: " + fromTimestamp);
}
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
The Legacy Approach: java.util.Date and java.sql.Timestamp
Before Java 8, this was the standard way. It works but is less type-safe and more error-prone.
Inserting with java.util.Date
You can pass a java.util.Date object to setTimestamp().
import java.sql.*;
import java.util.Date;
public class LegacyDateTimeInsert {
// ... (DB_URL, USER, PASS from before)
public static void main(String[] args) {
// java.util.Date represents a point in time
Date now = new Date();
String sql = "INSERT INTO events (event_name, event_time) VALUES (?, ?)";
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
PreparedStatement pstmt = conn.prepareStatement(sql)) {
pstmt.setString(1, "Legacy Event");
// Use setTimestamp() for java.util.Date / java.sql.Timestamp
pstmt.setTimestamp(2, new java.sql.Timestamp(now.getTime()));
int rowsAffected = pstmt.executeUpdate();
System.out.println(rowsAffected + " legacy row inserted!");
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Retrieving with java.util.Date
You retrieve a DATETIME as a java.sql.Timestamp (which extends java.util.Date).
import java.sql.*;
import java.util.Date;
public class LegacyDateTimeSelect {
// ... (DB_URL, USER, PASS from before)
public static void main(String[] args) {
String sql = "SELECT event_time FROM events WHERE event_name = 'Legacy Event'";
try (Connection conn = DriverManager.getConnection(DB_URL, USER, PASS);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery(sql)) {
if (rs.next()) {
// Get the value as a java.sql.Timestamp
java.sql.Timestamp timestamp = rs.getTimestamp("event_time");
System.out.println("Retrieved time (Timestamp): " + timestamp);
// You can use it as a java.util.Date
Date date = timestamp;
System.out.println("As java.util.Date: " + date);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
}
Common Pitfalls and Best Practices
-
Time Zone Hell (The #1 Problem!)
- The Trap: If you use
ZonedDateTimeorInstantin Java and then store it naively, you might run into issues. The JDBC driver might convert it to the server's or JVM's default time zone, leading to incorrect times in your database. - The Solution: Stick with
LocalDateTimeforDATETIMEcolumns. If you must use a time zone, convert it to UTC and store it in aTIMESTAMPcolumn (MySQL'sTIMESTAMPis time-zone aware and converts to UTC on storage). Or, store the offset (ZoneOffset.UTC) alongside yourDATETIMEif you need to reconstruct the original time.
- The Trap: If you use
-
String Manipulation is a Bad Idea
- The Trap: Don't try to format
LocalDateTimeinto a string like"yyyy-MM-dd HH:mm:ss"and then usesetString()to insert it. Similarly, don't retrieve it as a string and parse it withDateTimeFormatter. This is brittle, error-prone, and bypasses the driver's type-checking. - The Solution: Always use
PreparedStatement.setObject()and `ResultSet.getObject
- The Trap: Don't try to format
