记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.Timestampjava.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 }

注:如果大佬们有其它更好的解决方案,还请不吝赐教 (手动狗头)。

原文地址:https://www.cnblogs.com/bzfsdr/p/13495388.html