前言
在日常的开发中我们经常会用到日期类型,相应的与数据库对应的数据类型包括date、datetime、timestamp、time等类型,但是对于如何使用数据库的日期类型,有时候并不太清楚。
本文中将详细做一下分析解读。
对比
| 类型 | 显示格式 | 占用空间 | 最小值 | 最大值 | 说明 |
|---|---|---|---|---|---|
| date | YYYY-MM-DD | 3 bytes | 1000-01-01 | 9999-12-31 | |
| datetime | YYYY-MM-DD hh:mm:ss[.fraction] | 8 bytes | 1000-01-01 00:00:00 | 9999-12-31 23:59:59 | |
| timestamp | timestamp | 4 bytes | 1970-01-01 00:00:01 UTC | 2038-01-19 03:14:07 UTC | 存储的是从【1970-01-01 00:00:00 UTC】的毫秒数 |
注意:datetime和timestamp的格式一致,但是timestamp会跟随设置的时区变化而变化,datetime保存的是日期的绝对值。datetime和timestamp的毫秒精度都是6位。
MySQL DateType 存储格式
DATE
MYSQL_TYPE_DATE类型使用3个字节存储,小端存储。3个字节一共24个比特位,其中从低到高(从右到左)前5位,表示日期,接着的从低到高4位表示月份,剩余的位数表示年份。
DATETIME
MYSQL_TYPE_DATETIME2类型使用5个字节存储,并且根据时间精度的不同,额外需要不同的字节存储数据,时间精度部分为大端存储。
年月日时分秒的内容存储在基础的5个字节中,5个字节一共40位,从左往右前18位表示年月(年份 * 13 + 月份),其中最高位表示符号,最高位为1表示是正的,为0表示是负的,接着的5位表示日期,剩余的17位中,按照顺序,5位表示时,6位表示分,6位表示秒。因为时间精度最多为6位,一个字节表示两位,所以时间精度为1或者2的时候,使用一个额外的字节表示时间精度,时间精度为3或者4的时候,使用两个额外的字节表示时间精度,时间精度为5或者6的时候,使用三个额外的字节表示时间精度。
TIMESTAMP
MYSQL_TYPE_TIMESTAMP2类型使用4个字节存储,大端存储,并且根据时间精度的不同,额外需要不同的字存储数据,时间精度部分也使用大端存储;如果时间精度为1或者2,则4个字节之外还需要1个字节存储数据;如果时间精度为3或者4,则4个字节之外还需要2个字节存储数据;如果时间精度为5或者6,则4个字节之外还需要3个字节存储数据。
Mybatis使用
Mybatis中包含的日期类型只有两种(此时的DATE指的是java.sql.Date,不是java.util.Date,要注意两者的区别。同理,TIMESTAMP指的是java.sql.Timestamp)
- jdbcType=DATE
- jdbcType=TIMESTAMP
在实际开发过程中,如果我们将java.util.Date当做参数传递给Mapper的时候,需要指定jdbctype。
- 假如我们不指定jdbcType,那么这个日期会自动转化会MySQL的timestamp
- 指定jdbcType=TIMESTAMP结果同上。
- 指定jdbcType=DATE,那么MyBatis会将传入参数截取为2018-06-15,变成Date类型
使用java.util.Date作为参数传递给Mapper时,不管MySQL的日期字段类型是date、datetime或者timestamp中的哪一种,默认缺省情况下,MyBatis都能够自动做出类型转换,可以直接使用 =、>、<、>=、<=符号来进行筛选。
但是,当我们手动指定jdbcType=DATE的时候,MyBatis会自动截取掉时间,只保留日期。如果MySQL的日期字段类型是datetime或者timestamp一定不要这么写,否则属于画蛇添足,自讨没趣。