记mysql datetime转成pojo date时使用equals的坑
场景:
需要记录用户设备激活时间。
准备工作:
1、DDL:
1 ALTER TABLE t_customers 2 ADD COLUMN activate_time datetime NOT NULL DEFAULT '1970-01-01 00:00:00' COMMENT '设备激活时间(首次登陆app时间)';
2、pojo:
1 /** 2 * 设备激活时间(有设备号的时间) 3 */ 4 @Column(name = "activate_time") 5 private Date activateTime = DateFormatUtil.string2date("1970-01-01 00:00:00", DateFormatUtil.YYYY_MM_DD_HH_MM_SS); 6 7 public Date getActivateTime() { 8 return activateTime; 9 } 10 11 public void setActivateTime(Date activateTime) { 12 this.activateTime = activateTime; 13 }
遇到的问题:
因为激活时间只能记录一次,此后不能再改所以我判断了如果用户的激活时间不是默认值DateFormatUtil.string2date("1970-01-01 00:00:00", DateFormatUtil.YYYY_MM_DD_HH_MM_SS)我才会取set。
1 Date defVal = DateFormatUtil.string2date("1970-01-01 00:00:00", DateFormatUtil.YYYY_MM_DD_HH_MM_SS); 2 assert defVal != null; 3 if (getActivateTime().equals(defVal)) { 4 setActivateTime(new Date()); 5 }
预想的情况是能将activateTime修改为当前时间,但实际上未修改成功。
通过debug发现getActivateTime()的实际类型为java.sql.Timestamp,所以getActivateTime().equals(defVal)中的equals调用的是Timestamp的equals(踩坑的原因是java.sql.Timestamp是java.util.Date的子类,通过IDEA查看源码的时候会跳到Date中去)。
而Timestamp.equals的源码如下:
1 public boolean equals(java.lang.Object ts) { 2 if (ts instanceof Timestamp) { 3 return this.equals((Timestamp)ts); 4 } else { 5 return false; 6 } 7 }
当传入类型不为Timestamp是直接返回false,这也就是为什么activateTime未能按照预期修改为当前时间的原因了。
解决方案:
结合自身经验,我依次查看了Date.equals、以及他们的compareTo、getTime方法,得出的一下解约方案:
1、用Date.equals(Timestamp),而非是Timestamp.equals(Date)。
2、使用compareTo代替equals。
3、使用getTime()替代equals。
最终结合自身实际情况我选择了第二种,实现如下:
1 Date defVal = DateFormatUtil.string2date("1970-01-01 00:00:00", DateFormatUtil.YYYY_MM_DD_HH_MM_SS); 2 assert defVal != null; 3 if (getActivateTime().compareTo(defVal) == 0) { 4 setActivateTime(new Date()); 5 }
注:如果大佬们有其它更好的解决方案,还请不吝赐教 (手动狗头)。