今天半抱,在做黑馬的秒殺項(xiàng)目時(shí)發(fā)現(xiàn)了一個(gè)關(guān)于MySQL連接配置信息serverTimezone的問(wèn)題膜宋。
問(wèn)題
秒殺項(xiàng)目為了保證商品信息加載的速度,會(huì)用到緩存減少數(shù)據(jù)庫(kù)訪問(wèn)的壓力秋茫。應(yīng)該在秒殺開(kāi)始前將數(shù)據(jù)從MySQL中取出并存入Redis中。
秒殺商品實(shí)體類:
public class SeckillGoods implements Serializable{
@Column(name = "status")
private String status;//審核狀態(tài)肛著,0未審核圆兵,1審核通過(guò)枢贿,2審核不通過(guò)
@Column(name = "start_time")
private Date startTime;//開(kāi)始時(shí)間
@Column(name = "end_time")
private Date endTime;//結(jié)束時(shí)間
@Column(name = "stock_count")
private Integer stockCount;//剩余庫(kù)存數(shù)
//Getter Setter及無(wú)關(guān)屬性已刪除
}
秒殺商品表結(jié)構(gòu):
create table changgou_seckill.tb_seckill_goods
( status char null comment '審核狀態(tài),0未審核局荚,1審核通過(guò)统抬,2審核不通過(guò)',
start_time datetime null comment '開(kāi)始時(shí)間',
end_time datetime null comment '結(jié)束時(shí)間',
# 省略無(wú)關(guān)屬性..
) charset = utf8;
在跟著視頻做訪問(wèn)MySQL數(shù)據(jù)庫(kù)操作時(shí)發(fā)現(xiàn)即使使用相同的代碼也無(wú)法取出當(dāng)前時(shí)間段符合秒殺條件的商品信息。經(jīng)過(guò)一段時(shí)間的debug,發(fā)現(xiàn)聪建,視頻中的“當(dāng)前時(shí)間”是2019年,而我的”當(dāng)前時(shí)間“是2020年茫陆,能查出來(lái)才怪金麸。于是我修改代碼將“當(dāng)前時(shí)間”固定為2019年。
可是事情發(fā)展總是沒(méi)有那么順利簿盅,即使是使用修改后的代碼進(jìn)行查詢挥下,tk-MyBatis返回的數(shù)據(jù)仍然是空的。
看到這桨醋,我首先想到判斷是否為SQL語(yǔ)句有誤:
SELECT id,status,start_time,end_time FROM tb_seckill_goods WHERE (
status = '1'
and stock_count > 0
and start_time <= '2019-05-23 16:14:23'
and end_time >= '2019-05-23 16:14:23')
沒(méi)問(wèn)題棚瘟。
接著,我懷疑是否是tk-MyBatis生成的SQL語(yǔ)句存在問(wèn)題喜最。
所以偎蘸,我開(kāi)啟debug模式,一步步跟蹤tk-MyBatis的源代碼瞬内,最后在org.apache.ibatis.executor.statement.PreparedStatementHandler#query找到了生成的完整的SQL語(yǔ)句:
我一看迷雪,這和我固定的時(shí)間不太一樣:
我又一番debug,終于在com.mysql.cj.ClientPreparedQueryBindings#setTimestamp找到了原因:
可以看到它通過(guò)com.mysql.cj.protocol.a.NativeServerSession#getDefaultTimeZone獲取到時(shí)區(qū)虫蝶,然后使用SimpleDateFormat完成轉(zhuǎn)換:
和下面的例子差不多:
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
simpleDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = new Date();
System.out.println(date);
String format = simpleDateFormat.format(date);
System.out.println(format);
測(cè)試結(jié)果:
Mon Nov 02 16:21:57 CST 2020
2020-11-02 08:21:57
正好章咧,差8個(gè)小時(shí),不就是UTC+8能真,時(shí)區(qū)問(wèn)題赁严,小意思。
解決
再次檢查視頻提供的配置文件粉铐,發(fā)現(xiàn)他們的MySQL的連接信息:
jdbc:mysql://192.168.29.140:3306/changgou_seckill?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC
噢疼约,太簡(jiǎn)單了,直接改:
jdbc:mysql://192.168.29.140:3306/changgou_seckill?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC%2B8
大功告成