大多数数据库支持三种形式的日期时间字段,即 DATE、TIME 和 TIMESTAMP。它们中的每一个在 JDBC 中都有一个对应的类,并且它们中的每一个都扩展了java.util.Date。这三个是:
- java.sql.Date表示 SQL DATE,存储年、月和日,没有时间组件。java.sql.Date 不考虑时区。
- java.sql.Time表示 SQL TIME,仅包含有关小时、分钟、秒和毫秒的信息,不包含日期组件。
- java.sql.Timestamp表示 SQL TIMESTAMP,它包含精确到纳秒精度的日期和时间信息。
让我们检查下表,参考前 5 个数据库(不按顺序)日期时间数据类型:
Database | SQL DATE | SQL TIME | SQL TIMESTAMP | Source |
---|---|---|---|---|
MySQL / MariaDB | DATE DATETIME | TIME | TIMESTAMP | Link Link |
PostgreSQL | DATE | TIME TIME WITH TIME ZONE | TIMESTAMP TIMESTAMP WITH TIME ZONE | Link |
Oracle | DATE | TIMESTAMP TIMESTAMP WITH TIME ZONE TIMESTAMP WITH LOCAL TIME ZONE | Link | |
Microsoft SQL Server | DATE SMALLDATETIME DATETIME DATETIME2 DATETIMEOFFSET | TIME | Link | |
IBM Db2 | DATE | TIME | TIMESTAMP | Link |
我把来源,我的参考放在最右边的栏中。如我错了请纠正我
使用 JDBC 类
选择哪个类取决于字段的 SQL 类型。PreparedStatement 具有所有三个值的设置器,setDate() 用于 java.sql.Date,setTime() 用于 java.sql.Time 和 setTimestamp() 用于 java.sql.Timestamp。
让我们举个例子,我们在数据库中创建一个测试表。对于本文,我将使用 MySQL。
CREATE TABLE test_datetime (
dtm_date DATE,
dtm_time TIME,
dtm_timestamp TIMESTAMP,
obj_date DATE,
obj_time TIME,
obj_timestamp TIMESTAMP
);
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
public class SqlDateTimeInsertExample {
public static void main(String[] args) throws Exception {
// (1) connect to mysql database
String url = "jdbc:mysql://localhost/coffeehouse?serverTimezone=Asia/Singapore";
Class.forName("com.mysql.cj.jdbc.Driver");
try (Connection conn = DriverManager.getConnection(url, "barista", "cappuccino")) {
// (2) set java.sql.Date, Time, and Timestamp with current Date (and time)
java.util.Date utilDate = new java.util.Date();
java.sql.Date sqlDate = new java.sql.Date(utilDate.getTime());
java.sql.Time sqlTime = new java.sql.Time(utilDate.getTime());
java.sql.Timestamp sqlTS = new java.sql.Timestamp(utilDate.getTime());
// (3) insert java.sql.Date, Time and Timestamp (including objects) to DB
String sql = "INSERT INTO test_datetime("
+ "dtm_date, dtm_time, dtm_timestamp,"
+ "obj_date, obj_time, obj_timestamp) VALUES (?,?,?,?,?,?)";
try (PreparedStatement pst = conn.prepareStatement(sql)) {
pst.setDate(1, sqlDate);
pst.setTime(2, sqlTime);
pst.setTimestamp(3, sqlTS);
pst.setObject(4, utilDate);
pst.setObject(5, utilDate);
pst.setObject(6, utilDate);
// (4) execute update
pst.executeUpdate();
}
}
}
}
如上例,使用 setObject(int parameterIndex , x Object); 我们可以只给最后三个参数一个 util.Date ,它们可以毫无问题地接受它(这也发生在另一个 JDBC 驱动程序中,而不仅仅是 MySQL)。但是只是懒惰地使用 setObject(...) 会导致一些问题,包括数据(或部分数据)丢失。
注意: URL 后缀 ?serverTimezone=Asia/Singapore 是为了抑制:线程“main”中的异常 java.sql.SQLException:服务器时区值“马来半岛标准时间”无法识别或代表多个时区。如果要使用时区支持,则必须配置服务器或 JDBC 驱动程序(通过 serverTimezone 配置属性)以使用更具体的时区值。
(你能看到上面 MySQL JDBC 错误消息中的错字吗?:p)
连接mysql确认结果:
$ mysql -u barista -p
Enter password: **********
Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 9
Server version: 5.5.27 MySQL Community Server (GPL)
mysql> connect coffeehouse
Connection id: 10
Current database: coffeehouse
mysql> select * from test_datetime;
+------------+----------+---------------------+------------+----------+---------------------+
| dtm_date | dtm_time | dtm_timestamp | obj_date | obj_time | obj_timestamp |
+------------+----------+---------------------+------------+----------+---------------------+
| 2019-08-15 | 15:48:19 | 2019-08-15 15:48:19 | 2019-08-15 | 15:48:19 | 2019-08-15 15:48:19 |
+------------+----------+---------------------+------------+----------+---------------------+
1 row in set (0.00 sec)