记录下最近刚操作MongoDB出现的坑
第一种方式
使用MongoTemplate操作,这个是在springboot中整合了mongodb的常见方法。
- 添加依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
- application.yml添加配置
spring:
data:
mongodb:
uri: mongodb://username:password@ip:port/dbname
- 使用方法
@Component
public class MongoTest {
@Autowired private MongoTemplate mongoTemplate;
public <T> List<T> findAll(Class<T> clazz) {
//可以再加一个参数指定collection
//return mongoTemplate.findAll(clazz, collection);
return mongoTemplate.findAll(clazz);
}
public <T> T findOne(Class<T> clazz) {
Query query = new Query(Criteria.where("id").is("xxx");
return mongoTemplate.findOne(query, clazz);
}
}
- 问题
MongoTemplate整合了大量常见的方法,基本满足了所有的使用,以上代码只是简单的示意,详情看官方文档或者专门介绍这个的书和博客。但是使用这个的时候我发现了一个天坑。问题就是在传入一个类获取结果,就是代码中的Class clazz。有一个大问题,如果MongoDB中的字段有首字母大写的,就很尴尬了。因为Java的字段是大小写敏感的,如果Java的映射类字段设置成首字母大写,和MonggoDB一致,那么findAll是没有问题的,可以正常获取到值。但是用到条件查询时,就会抛出一个映射类没有小写开头字段的异常。如果设置成小写,那么查询会获取不到结果。
- 解决方法
我大小写做了很多手脚,发现还是不行。没办法,只能使用第二种方式解决,就是字段的映射关系自己来写。
第二种方式
-
第二种方式和第一种的关系就相当于是ORM框架和jdbc的关系。上面的MongoTemplate帮忙封装了字段的映射,但是不能正常映射,所以就是用这个方法来手动指定。
-
使用方法
//创建Mongo对象
Mongo mongo = new Mongo(ip, port);
//连接dbname数据库,如果不存在则创建
DB myDB = mongo.getDB(dbname);
//从该数据库中获取名为coll的数据集合,如果不存在则创建collection
DBCollection collection = myDB.getCollection(coll);
//查询条件
BasicDBObject d = new BasicDBObject();
//条件查询,这个值存在就加到条件中
if (!StringUtils.isEmpty(_name))
d.put("name", _name);
//总条目数
long count = collection.count(d);
//条件分页查询,start就是开始查询位置,(page - 1) * pageSize,limit就是页面条目数
DBCursor dbObjects = collection.find(d).skip(start).limit(limit);
dbObjects.toArray().forEach(dbObject -> {
//处理遍历结果,这里可以传入映射类,手动取值自己映射
...
});
坑
- 对同一个条件进行大小区间的筛选
错误:
BasicDBObject d = new BasicDBObject();
d.put("update_time", new BasicDBObject("$gte", start));
d.put("update_time", new BasicDBObject("$lte", end));
这样后者会顶掉前者
正确:
BasicDBObject d = new BasicDBObject();
BasicDBObject _time = new BasicDBObject();
_time.put("$gte", start);
_time.put("$lte", end);
d.put("update_time", _time);
- 连接MongoDB需要账号密码
MongoCredential credential = MongoCredential.createCredential(username, dbname, password.toCharArray());
MongoClient mongoClient = new MongoClient(new ServerAddress(ip, Integer.parseInt(port)), Arrays.asList(credential));
DB database = mongoClient.getDB(dbname);//获取数据库
//从该数据库中获取名为mycollection 的数据集合,如果不存在则创建collection
DBCollection collection = database.getCollection(coll);