java用spring-data-mongodb操作mongodb的时间问题
2017-01-22 12:59
661 查看
最近项目用到了mongodb,做了个时间段查询,自己调试的时候,发现把时间放到查询条件类QueryBuilder中之后就会自动向前推8小时。。纠结了好几天,终于找到答案,这里跟大家分享一下,希望大家会避免。
先贴出主要代码:
当queryBuilder.put(“createTime”).greaterThanEquals(startDate);执行之后,debug调试查看queryBuilder会发现startDate的值向前推了8小时,百度了半天发现是时区的问题,可是也没有具体解答,只好看源码跟进问题。
一开始以为是QueryBuilder的greaterThanEquals等方法做了时区的转换,于是找出来greaterThanEquals方法的源码:
源码跟进来之后,发现是 _query.put(_currentKey, value);这句之后时间就会变,大家看图,我们先看传进去的时间,2017年01月10日10点整,如下图:
再来看put之后的_query值,下图:
可以看到,变成了2017年1月7日2点,于是又把问题放到了_query上面,看他的put里干了什么,我们要知道_query是什么类型。继续看源码:
初始化的时候创建了BasicDBObject对象,继续到BasicDBObject中看put方法,如下:
到这也不用看了,发现put方法是直接用的父类,点进去是HashMap类的put方法。。。到这线索没了,已疯。。。左思右想,spring-data-mongo肯定不会这么坑,一定是我的打开方式不对,于是想先往BasicDBObject中put个时间值,再把他get出来,看看get出来的值还改变吗,结果get出来的值没有向前推8小时,没有没有没有。
为了进一步证实调用数据库查询时用的是我们传进去的时间,还是向前推8小时之后的时间,我在mongodb中插入一条时间为2017-01-10 10:00:00的数据,然后在java中传2017-01-10 10:00:00这个时间条件进行查询,可以看到put之后仍然变成了2017-01-10 02:00:00,可是查询结果确实是查到了时间为2017-01-10 10:00:00的数据。
可以看到,这与我们的期望值一致,可是中间出了些问题,纠结了一段时间,突然想到会不会是toString的时候把时区改了呢,导致打印和显示的时候出来的是格林时间,事实证明真的是这样,BasicDBObject在toString方法中有个处理java.util.Date的地方,把时区设置成了格林时间,如下图:
现在我该说什么。。我们眼睛看到的,未必是真实的。。。
至此,时间的问题就分析完了,分享给大家,希望大家以后遇到不要绕弯路~第一次写博客,有点紧张~有什么不对欢迎指正~~
先贴出主要代码:
// 构建查询条件 QueryBuilder queryBuilder = new QueryBuilder(); Date startDate = DateUtil.fromStringToDate("yyyy-MM-dd HH:mm:ss", "2017-01-07 10:00:00"); queryBuilder.put("createTime").greaterThanEquals(startDate); // 要查询的字段 BasicDBObject fieldsObject = new BasicDBObject(); fieldsObject.put("name", 1); fieldsObject.put("age", 1); fieldsObject.put("createTime", 1); // 执行查询 Query query = new BasicQuery(queryBuilder.get(), fieldsObject); List<Map> list = mongoTemplate.find(query, Map.class, COLLECTION);
当queryBuilder.put(“createTime”).greaterThanEquals(startDate);执行之后,debug调试查看queryBuilder会发现startDate的值向前推了8小时,百度了半天发现是时区的问题,可是也没有具体解答,只好看源码跟进问题。
一开始以为是QueryBuilder的greaterThanEquals等方法做了时区的转换,于是找出来greaterThanEquals方法的源码:
public QueryBuilder greaterThanEquals(Object object) { addOperand(QueryOperators.GTE, object); return this; } //里面做了一个addOperand方法,我们看addOperand的源码 private void addOperand(String op, Object value) { if(op == null) { if (_hasNot) { value = new BasicDBObject(QueryOperators.NOT, value); _hasNot = false; } // 这里预警,put之后_query里的时间就变了 _query.put(_currentKey, value); return; } Object storedValue = _query.get(_currentKey); BasicDBObject operand; if(!(storedValue instanceof DBObject)) { operand = new BasicDBObject(); if (_hasNot) { DBObject notOperand = new BasicDBObject(QueryOperators.NOT, operand); _query.put(_currentKey, notOperand); _hasNot = false; } else { _query.put(_currentKey, operand); } } else { operand = (BasicDBObject)_query.get(_currentKey); if (operand.get(QueryOperators.NOT) != null) { operand = (BasicDBObject) operand.get(QueryOperators.NOT); } } operand.put(op, value); }
源码跟进来之后,发现是 _query.put(_currentKey, value);这句之后时间就会变,大家看图,我们先看传进去的时间,2017年01月10日10点整,如下图:
再来看put之后的_query值,下图:
可以看到,变成了2017年1月7日2点,于是又把问题放到了_query上面,看他的put里干了什么,我们要知道_query是什么类型。继续看源码:
public QueryBuilder() { _query = new BasicDBObject(); }
初始化的时候创建了BasicDBObject对象,继续到BasicDBObject中看put方法,如下:
public class BasicBSONObject extends LinkedHashMap<String,Object> implements BSONObject { ... public Object put( String key , Object val ){ return super.put( key , val ); } ... }
到这也不用看了,发现put方法是直接用的父类,点进去是HashMap类的put方法。。。到这线索没了,已疯。。。左思右想,spring-data-mongo肯定不会这么坑,一定是我的打开方式不对,于是想先往BasicDBObject中put个时间值,再把他get出来,看看get出来的值还改变吗,结果get出来的值没有向前推8小时,没有没有没有。
为了进一步证实调用数据库查询时用的是我们传进去的时间,还是向前推8小时之后的时间,我在mongodb中插入一条时间为2017-01-10 10:00:00的数据,然后在java中传2017-01-10 10:00:00这个时间条件进行查询,可以看到put之后仍然变成了2017-01-10 02:00:00,可是查询结果确实是查到了时间为2017-01-10 10:00:00的数据。
可以看到,这与我们的期望值一致,可是中间出了些问题,纠结了一段时间,突然想到会不会是toString的时候把时区改了呢,导致打印和显示的时候出来的是格林时间,事实证明真的是这样,BasicDBObject在toString方法中有个处理java.util.Date的地方,把时区设置成了格林时间,如下图:
现在我该说什么。。我们眼睛看到的,未必是真实的。。。
至此,时间的问题就分析完了,分享给大家,希望大家以后遇到不要绕弯路~第一次写博客,有点紧张~有什么不对欢迎指正~~
相关文章推荐
- 使用Spring Data MongoDB 做聚合操作出现的问题及解决方案
- java操作Mongodb,Spring-data-mongo简单配置
- JAVA 处理 Spring data mongodb 时区问题
- java 操作mongoDB(DBobject,非spring data)
- spring-data-mongodb必须了解的操作
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- spring data mongodb 提供的MongoTemplate 模板,进行Aggregation操作实践
- Spring Data MongoDB 一:入门篇(环境搭建、简单的CRUD操作)
- 使用springdata操作mongodb的例子
- Spring Data MongoDB 级联操作
- JAVA操作数据库一(Spring data jpa)
- java操作MongoDB遇到的一些问题
- Spring Data MongoDB 二:添加、删除操作
- JAVA数据库操作二(多个数据库操作+Spring data + jpa)
- spring data mongodb的Converter问题
- spring-data-mongodb 对于collection的upsert操作
- Java 访问 MongoDB (使用Spring-Data-MongoDB)
- 使用spring-data-mongodb操作mongodb
- 通过使用spring-data-mongodb操作mongodb
- Spring Data MongoDB 六:进阶Aggregation操作(上)