大多数数据库支持三种形式的日期时间字段,即 DATE、TIME 和 TIMESTAMP。它们中的每一个在 JDBC 中都有一个对应的类,并且它们中的每一个都扩展了java.util.Date。这三个是:
让我们检查下表,参考前 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 |
我把来源,我的参考放在最右边的栏中。如我错了请纠正我
选择哪个类取决于字段的 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)