Spring Data Mongo如何仅保存日期(不含时间)?
嘿,我完全懂你遇到的困扰——想用Spring把日期存成纯YYYY-MM-DD格式到MongoDB,试了@DateTimeFormat的两种ISO配置,结果数据库里还是带着时间戳。这其实是因为Java的Date类型和MongoDB的存储特性在捣鬼,咱们来一步步解决:
方法一:用Java 8+的LocalDate替代Date(推荐)
LocalDate是Java 8引入的日期类,本身就只包含年、月、日,没有时间部分,完美匹配你的需求。配合Spring的注解就能直接用:
import java.time.LocalDate; import org.springframework.format.annotation.DateTimeFormat; public class JourneyEntity { // 用ISO.DATE格式处理前端的日期字符串,同时存储到MongoDB时只保留日期 @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) private LocalDate journeyDate; // 别忘了添加getter和setter public LocalDate getJourneyDate() { return journeyDate; } public void setJourneyDate(LocalDate journeyDate) { this.journeyDate = journeyDate; } }
Spring Data MongoDB对LocalDate有原生支持,存到数据库后会自动转成MongoDB的Date类型,但时间部分会默认设为00:00:00。后续查询时,你可以直接用日期范围来匹配:
// 查询2018-01-26的所有文档 db.journeys.find({ journeyDate: { $gte: ISODate("2018-01-26T00:00:00Z"), $lt: ISODate("2018-01-27T00:00:00Z") } })
方法二:手动清零Date的时间部分
如果坚持要用Java的Date类型,那在保存前需要把时间部分手动设为当天的起始时间(00:00:00):
import java.time.LocalDate; import java.time.ZoneId; import java.util.Date; // 设置当前日期并清零时间 LocalDate today = LocalDate.now(); Date journeyDate = Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant()); // 把这个journeyDate赋值给实体类再保存 JourneyEntity entity = new JourneyEntity(); entity.setJourneyDate(journeyDate); journeyRepository.save(entity);
这样存到MongoDB的journeyDate就是当天零点的时间戳,查询时同样可以用上面的范围条件来精准匹配日期。
方法三:自定义MongoDB转换器,存为字符串格式
如果你希望数据库里直接存储"2018-01-26"这样的字符串,可以自定义类型转换器,让Spring Data把Date和字符串互相转换:
1. 写转换器类
import org.springframework.core.convert.converter.Converter; import java.text.SimpleDateFormat; import java.util.Date; // Date转字符串 public class DateToStringConverter implements Converter<Date, String> { private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public String convert(Date source) { return dateFormat.format(source); } } // 字符串转Date public class StringToDateConverter implements Converter<String, Date> { private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); @Override public Date convert(String source) { try { return dateFormat.parse(source); } catch (Exception e) { throw new IllegalArgumentException("日期格式错误,请使用yyyy-MM-dd", e); } } }
2. 注册转换器到MongoDB配置
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.data.mongodb.core.convert.MongoCustomConversions; import java.util.Arrays; @Configuration public class MongoConfig { @Bean public MongoCustomConversions mongoCustomConversions() { return new MongoCustomConversions(Arrays.asList( new DateToStringConverter(), new StringToDateConverter() )); } }
之后存到MongoDB的journeyDate就是纯字符串格式,查询时直接匹配字符串即可:
db.journeys.find({journeyDate: "2018-01-26"})
为什么之前的@DateTimeFormat没用?
这里要注意:@DateTimeFormat主要是用来处理前端请求参数和后端响应的格式化,比如把前端传来的"2018-01-26"字符串转成Java的Date对象,或者把Date转成字符串返回给前端。但它不会改变MongoDB存储Date类型的本质——MongoDB的Date类型本身就包含时间戳,所以光靠这个注解没法去掉时间部分。
内容的提问来源于stack exchange,提问作者Srini Kandula

