MySQL時(shí)間類型與Java日期時(shí)間類對(duì)應(yīng)關(guān)系示例詳解
一、MySQL 時(shí)間類型與 Java 類型對(duì)應(yīng)關(guān)系
| MySQL 類型 | 范圍/描述 | Java 對(duì)應(yīng)類型 | 精度級(jí)別 |
|---|---|---|---|
| ??DATE?? | '1000-01-01' - '9999-12-31' | java.time.LocalDate | 日期 |
| ??TIME?? | '-838:59:59' - '838:59:59' | java.time.LocalTime | 時(shí)間 |
| ??DATETIME?? | '1000-01-01 00:00:00' - '9999-12-31 23:59:59' | java.time.LocalDateTime | 毫秒/微秒 |
| ??TIMESTAMP?? | '1970-01-01 00:00:01' - '2038-01-19 03:14:07' | java.time.Instantjava.sql.Timestamp | 秒/毫秒 |
| ??YEAR?? | 1901 - 2155 | java.time.Yearjava.lang.Integer | 年 |
二、JDBC 操作映射關(guān)系
1. 從數(shù)據(jù)庫讀取數(shù)據(jù)
try (ResultSet rs = stmt.executeQuery("SELECT * FROM time_table")) {
while (rs.next()) {
LocalDate date = rs.getObject("date_column", LocalDate.class);
LocalTime time = rs.getObject("time_column", LocalTime.class);
LocalDateTime dateTime = rs.getObject("datetime_column", LocalDateTime.class);
Instant timestamp = rs.getObject("ts_column", Instant.class);
}
}2. 向數(shù)據(jù)庫寫入數(shù)據(jù)
PreparedStatement ps = conn.prepareStatement(
"INSERT INTO time_table (date_column, time_column, datetime_column, ts_column) " +
"VALUES (?, ?, ?, ?)");
ps.setObject(1, LocalDate.now());
ps.setObject(2, LocalTime.now());
ps.setObject(3, LocalDateTime.now());
ps.setObject(4, Instant.now());
ps.executeUpdate();三、MySQL 時(shí)間類型詳細(xì)對(duì)比
| ??特性?? | DATE | TIME | DATETIME | TIMESTAMP | YEAR |
|---|---|---|---|---|---|
| ??時(shí)區(qū)敏感?? | 否 | 否 | 否 | ??是?? | 否 |
| ??自動(dòng)初始化?? | 否 | 否 | 否 | ??是?? | 否 |
| ??自動(dòng)更新?? | 否 | 否 | 否 | ??是?? | 否 |
| ??存儲(chǔ)空間(字節(jié))?? | 3 | 3 | 5-8 | 4 | 1 |
| ??微秒精度支持?? | - | MySQL 5.6+ | MySQL 5.6+ | MySQL 5.6.4+ | - |
| ??2038年限制?? | 無 | 無 | 無 | ??有?? (2038年) | 無 |
四、微秒精度處理(MySQL 5.6+)
// Java 端處理微秒(MySQL DATETIME(6))
LocalDateTime ldt = LocalDateTime.now()
.withNano(456000000); // 456毫秒
// MySQL 創(chuàng)建表
CREATE TABLE events (
event_time DATETIME(6) // 支持微秒級(jí)精度
);五、時(shí)區(qū)處理最佳實(shí)踐
1. 時(shí)間存儲(chǔ)策略
// 寫入統(tǒng)一使用 UTC 時(shí)間
ps.setObject(4, Instant.now()); // UTC 時(shí)間戳
// 讀取時(shí)轉(zhuǎn)換為本地時(shí)間
Instant dbTime = rs.getObject("event_time", Instant.class);
ZonedDateTime localTime = dbTime.atZone(ZoneId.systemDefault());2. MySQL 服務(wù)器配置
-- 檢查時(shí)區(qū)設(shè)置 SELECT @@global.time_zone, @@session.time_zone; -- 推薦設(shè)置為 UTC SET GLOBAL time_zone = '+00:00';
六、特殊場(chǎng)景處理方案
1. 日期范圍統(tǒng)計(jì)
LocalDate start = LocalDate.of(2023, 1, 1);
LocalDate end = LocalDate.of(2023, 12, 31);
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM orders WHERE order_date BETWEEN ? AND ?");
ps.setObject(1, start);
ps.setObject(2, end);2. 時(shí)間區(qū)間查詢(TIMESTAMP + 時(shí)區(qū))
Instant startInstant = ZonedDateTime.of(
2023, 5, 1, 0, 0, 0, 0,
ZoneId.of("Asia/Shanghai")).toInstant();
PreparedStatement ps = conn.prepareStatement(
"SELECT * FROM transactions WHERE create_time >= ?");
ps.setObject(1, startInstant);3. 時(shí)間間隔計(jì)算(Java 端處理)
LocalDateTime orderTime = rs.getObject("order_time", LocalDateTime.class);
LocalDateTime deliveryTime = rs.getObject("delivery_time", LocalDateTime.class);
Duration interval = Duration.between(orderTime, deliveryTime);
System.out.printf("配送耗時(shí): %.1f小時(shí)", interval.toMinutes() / 60.0);七、傳統(tǒng) java.sql 類替代方案
| 傳統(tǒng)類 | Java 8+ 替代方案 | 使用場(chǎng)景 |
|---|---|---|
java.sql.Date | LocalDate | 只處理日期部分 |
java.sql.Time | LocalTime | 只處理時(shí)間部分 |
java.sql.Timestamp | Instant 或 LocalDateTime | 帶時(shí)區(qū)的時(shí)間戳/本地日期時(shí)間 |
轉(zhuǎn)換示例:
// 傳統(tǒng)轉(zhuǎn)現(xiàn)代
Timestamp ts = rs.getTimestamp("create_time");
LocalDateTime ldt = ts.toLocalDateTime();
// 現(xiàn)代轉(zhuǎn)傳統(tǒng)
LocalDateTime now = LocalDateTime.now();
Timestamp ts = Timestamp.valueOf(now);八、時(shí)區(qū)轉(zhuǎn)換流程圖
graph LR
A[業(yè)務(wù)系統(tǒng)時(shí)間\nLocalDateTime] -->|應(yīng)用時(shí)區(qū)| B[JVM 默認(rèn)時(shí)區(qū)]
B -->|轉(zhuǎn)換為UTC| C[Instant/UTC時(shí)間]
C -->|存儲(chǔ)至MySQL| D[TIMESTAMP列]
D -->|讀取為Instant| E[Java Instant類型]
E -->|轉(zhuǎn)換至目標(biāo)時(shí)區(qū)| F[用戶時(shí)區(qū)顯示]九、常見問題解決方案
??時(shí)區(qū)錯(cuò)亂問題??
// 明確設(shè)置JVM時(shí)區(qū)(啟動(dòng)參數(shù)) -Duser.timezone=Asia/Shanghai // JDBC連接指定時(shí)區(qū) jdbc:mysql://localhost/db?serverTimezone=Asia/Shanghai
??2038年TIMESTAMP溢出??
- 在 MySQL 8.0 升級(jí) TIMESTAMP 到 8 字節(jié)存儲(chǔ)
- 將 TIMESTAMP 改為 DATETIME 類型
??微秒精度丟失??
// 數(shù)據(jù)庫指定精度(DATETIME(6)) LocalDateTime ldt = LocalDateTime.now().withNano(123456000);
??跨時(shí)區(qū)同步問題??
- 統(tǒng)一使用 UTC 時(shí)間存儲(chǔ)(TIMESTAMP)
- 前端顯示時(shí)根據(jù)用戶時(shí)區(qū)轉(zhuǎn)換
總結(jié)建議
??類型選擇優(yōu)先級(jí)??:
- 日期 →
DATE↔LocalDate - 時(shí)間 →
TIME↔LocalTime - 完整時(shí)間 →
DATETIME↔LocalDateTime - 跨時(shí)區(qū)時(shí)間 →
TIMESTAMP↔Instant
- 日期 →
??最佳實(shí)踐??:
// 創(chuàng)建表規(guī)范 CREATE TABLE events ( id BIGINT PRIMARY KEY, event_date DATE, -- 日期類數(shù)據(jù) event_time TIME(3), -- 毫秒級(jí)時(shí)間 start_datetime DATETIME(6), -- 微秒級(jí)本地時(shí)間 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP -- 帶時(shí)區(qū)時(shí)間 ); // Java操作規(guī)范 repository.save(new Event( LocalDate.now(), LocalTime.now().truncatedTo(ChronoUnit.MILLIS), LocalDateTime.now().withNano(456000000), Instant.now() ));??重要原則??:
- 前端交互:字符串(ISO 8601格式)
- 業(yè)務(wù)層:java.time 類型
- 持久層:直接映射數(shù)據(jù)庫類型
- 存儲(chǔ)時(shí)態(tài):統(tǒng)一使用UTC標(biāo)準(zhǔn)時(shí)區(qū)
??調(diào)試技巧??:
-- MySQL查看實(shí)際存儲(chǔ)值 SELECT date_column, UNIX_TIMESTAMP(ts_column) AS timestamp_value, CONVERT_TZ(ts_column, '+00:00', @@session.time_zone) AS local_time FROM time_table;
掌握MySQL和Java時(shí)間類型的精確對(duì)應(yīng)關(guān)系,是處理國際化應(yīng)用、財(cái)務(wù)系統(tǒng)和時(shí)效敏感業(yè)務(wù)的基礎(chǔ)。遵循UTC存儲(chǔ)、本地化展示的原則,可規(guī)避90%的時(shí)區(qū)相關(guān)問題。
到此這篇關(guān)于MySQL時(shí)間類型與Java日期時(shí)間類對(duì)應(yīng)關(guān)系的文章就介紹到這了,更多相關(guān)MySQL時(shí)間類型與Java日期時(shí)間類內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
MySQL rand函數(shù)實(shí)現(xiàn)隨機(jī)數(shù)的方法
在mysql中,使用隨機(jī)數(shù)寫一個(gè)語句能一下更新幾百條MYSQL數(shù)據(jù)嗎?答案是肯定的,使用MySQL rand函數(shù),就可以使現(xiàn)在隨機(jī)數(shù)2016-09-09
Mysql中基本語句優(yōu)化的十個(gè)原則小結(jié)
這篇文章主要給大家總結(jié)介紹了Mysql中基本語句優(yōu)化的十個(gè)原則,通過學(xué)習(xí)與記住它們,在構(gòu)造sql時(shí)可以養(yǎng)成良好的習(xí)慣,文中介紹的相對(duì)比較詳細(xì)與簡(jiǎn)單明了,需要的朋友們可以參考借鑒,下面來一起看看吧。2017-06-06
windows下如何解決mysql secure_file_priv null問題
這篇文章主要介紹了windows下如何解決mysql secure_file_priv null問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-01-01
windows下在一臺(tái)機(jī)器上安裝兩個(gè)MYSQL數(shù)據(jù)庫的方法
正常安裝第一個(gè)mysql,在控制面板里停止第一個(gè)mysql服務(wù),將C:\Program Files\MySQL目錄下的所有目錄和文件copy到另外一個(gè)路徑,我這里是copy到E盤2013-10-10
MySQL的MRR(Multi-Range Read)優(yōu)化原理解析
MRR優(yōu)化是MySQL中一種重要的查詢優(yōu)化技術(shù),它通過減少磁盤I/O的隨機(jī)性和提高緩存效率,顯著提升了查詢性能,這篇文章主要介紹了MySQL的MRR(Multi-Range Read)優(yōu)化原理詳解,需要的朋友可以參考下2024-08-08
Mysql數(shù)據(jù)庫5.7升級(jí)到8.4的實(shí)現(xiàn)
很多情況需要升級(jí)MySQL的數(shù)據(jù)庫版本,本文主要介紹了Mysql數(shù)據(jù)庫5.7升級(jí)到8.4的實(shí)現(xiàn),文中通過圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-06-06
MySQL切分函數(shù)substring()的具體使用
這篇文章主要介紹了MySQL切分函數(shù)substring()的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2021-02-02

