Java 操作MongoDB,一般有两种方式,第一就是Spring Data MongoDB,第二是MongoDB原生API操作。现在都流行Spring Boot,故在实际开发中基本都用Spring Data MongoDB;但是对于初学者,乃至学生,就不推荐使用Spring Data MongoDB了,学习时候要知其然,而知其所以然。有学生就偷懒,使用Spring Data MongoDB,不知其所以然,导致老师问的时候一问三不知,根本解析不清楚MongoTemplate是啥玩意儿。
本篇讲解使用原生API操作MongoDB,也是为了解决有些学生刚学MongoDB时候的烦恼。
引入MongoDB驱动包,这里用maven坐标(非Maven工程直接下载jar包即可):
<dependency>
<groupId>org.mongodb</groupId>
<artifactId>mongo-java-driver</artifactId>
<version>3.12.10</version>
</dependency>
创建链接MongoDB的类:
package mongodb;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.ObjectUtils.Null;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.MongoDatabase;
/**
* MongoDB 操作类连接
* @author hlinfo.net
*
*/
public class MongodbConn {
//MongoDB数据库地址
private static String host="192.168.1.2";
// Mongodb端口号, 默认是27017
private static int port = 27017;
//Mongodb 用户名,没有设置可以为空
private static String userName="";
//mongoDB 密码,没有设置可以为空
private static String password="";
//MongoDB 默认链接的数据库
private static String databaseName="demo";
/**
* MongoDB连接对象
*/
private MongoClient client;
/**
* 不需要认证获取连接对象
*/
public void mongoClient(){
try {
//获取mongodb连接对象
client = new MongoClient(host,port);
} catch (Exception e) {
System.out.println("不需要认证获取连接对象失败:"+e);
}
}
/**
* 需要认证获取连接对象
*/
public void certifyMongoClient(){
try {
//连接到MongoDB
//ServerAddress()两个参数分别为 服务器地址 和 端口
ServerAddress serverAddress = new ServerAddress(host,port);
List<ServerAddress> addrs = new ArrayList<ServerAddress>();
addrs.add(serverAddress);
//createScramSha1Credential()三个参数分别为 用户名,数据库名,密码
MongoCredential credential = MongoCredential.createScramSha1Credential(userName, databaseName, password.toCharArray());
//List<MongoCredential> credentials = new ArrayList<MongoCredential>();
//credentials.add(credential);
MongoClientOptions options = MongoClientOptions.builder().build();
//通过连接认证获取MongoDB连接
client = new MongoClient(addrs,credential,options);
} catch (Exception e) {
System.out.println("需要认证的获取连接对象失败:"+e);
}
}
/**
* 获取数据库对象
* @param databaseName 数据库名
* @return MongoDatabase
*/
public MongoDatabase getDatabase(){
if(client == null){
//没有配置用户名和密码的情况
if(userName==null || "".equals(userName) || password==null || "".equals(password)) {
mongoClient();
}else {
//配置用户名和密码的情况
certifyMongoClient();
}
}
MongoDatabase database = client.getDatabase(databaseName);
return database;
}
/**
* 关闭连接对象
*/
public void close(){
if(client != null){
client.close();
}
client = null;
}
}
MongoDB操作类:
package mongodb;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.bson.types.ObjectId;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.mongodb.BasicDBObject;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.lang.Nullable;
import cn.hutool.core.bean.BeanUtil;
/**
* MongoDB 操作类
* @author hadoop
*
*/
public class MongodbHelper {
private MongoDatabase db;
private MongodbConn conn;
public MongodbHelper() {
super();
//获取数据库对象
if(db==null || conn ==null) {
conn = new MongodbConn();
db = conn.getDatabase();
}
}
/**
* 关闭连接对象
*/
public void closeDb() {
if(db!=null) {
conn.close();
}
}
/**
* //获取指定文档集合对象
* @param coll
* @return
*/
public MongoCollection<Document> getColl(String coll) {
MongoCollection<Document> mongocoll = db.getCollection(coll);
return mongocoll;
}
/**
* 保存一条数据
* @param coll,表名
* @param map
*/
public void insertOne(String coll,Map<String,Object> map) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
//将map转换为Document
Document document = new Document(map);
//插入文档
doc.insertOne(document);
}
/**
* 保存一条数据
* @param coll,表名
* @param json JSON对象字符串数据
*/
public void insertOne(String coll,String json) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
//将map转换为Document
Document document = Document.parse(json);
//插入文档
doc.insertOne(document);
}
/**
* 将一个对象插入到一个数据源。
* @param obj 要被插入的对象
* <p>
* 它可以是:
* <ul>
* <li>普通 POJO
* <li>List集合
* </ul>
* <b style=color:red>注意:</b> 如果是list,所有的对象必须类型相同,否则可能会出错
*
*/
public boolean insert(Object obj) {
if(obj==null) {
return false;
}
if(BeanUtil.isBean(obj.getClass())) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(obj));
//将map转换为Document
Document document = Document.parse(JSON.toJSONString(obj));
//插入文档
doc.insertOne(document);
}else if(obj instanceof ArrayList || obj instanceof LinkedList) {
Object firstObj = first(obj);
List<Document> list = new ArrayList<Document>();
Collection parseObj = (Collection) obj;
parseObj.forEach(item->{
Document doc = Document.parse(JSON.toJSONString(item));
list.add(doc);
});
insertMany(getClazzName(firstObj), list);
}
return true;
}
/**
* 保存多条数据
* @param coll 表名
* @param list 多个Document集合
*/
public void insertMany(String coll,List<Document> list) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
//插入文档
doc.insertMany(list);
}
/**
* 删除单条数据
* @param coll 表名
* @param params 筛选条件对象
* @return
*/
public long deleteById(String coll,BasicDBObject params) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
//删除单条数据
DeleteResult result = doc.deleteOne(params);
return result.getDeletedCount();
}
/**
* 删除单条数据
@param clazz 对象类型
@param params 筛选条件对象
@return
*/
public long deleteById(Class<?> clazz,BasicDBObject params) {
return deleteById(getClazzName(clazz),params);
}
/**
* 删除单条数据
@param clazz 对象类型
@param key 删除的主键名
@param value 删除的条件值
@return
*/
public long deleteById(Class<?> clazz,String key,Object value) {
if(clazz==null || key==null || value==null) {
return -1;
}
//设置条件参数
BasicDBObject params = new BasicDBObject(key, value);
return deleteById(getClazzName(clazz),params);
}
/**
* 删除多条数据
* @param coll 表名
* @param params 筛选条件对象
* @return
*/
public long delete(String coll,BasicDBObject params) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
//删除多条数据
DeleteResult result = doc.deleteMany(params);
return result.getDeletedCount();
}
/**
* 查询所有数据
* @param coll 表名
* @return
*/
public FindIterable<Document> query(String coll) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
return doc.find();
}
public <T> FindIterable<Document> query(Class<T> clazz) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(clazz));
return doc.find();
}
/**
* 根据条件查询数据
* @param coll 表名
* @param params 查询条件
* @return
*/
public FindIterable<Document> query(String coll,BasicDBObject params) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
return doc.find(params);
}
public FindIterable<Document> query(Class<?> clazz,Bson filter) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(clazz));
return doc.find(filter);
}
/**
* 根据主键_id查找对象
@param coll
@param id
@return
*/
public Document findById(String coll, String id) {
ObjectId _idobj = null;
try {
_idobj = new ObjectId(id);
} catch (Exception e) {
return null;
}
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
Document myDoc = doc.find(Filters.eq("_id", _idobj)).first();
return myDoc;
}
/**
* 分页查询
@param coll
@param params
@param page
@param limit
@return
*/
public MongoCursor<Document> queryByPage(String coll,BasicDBObject params, int page, int limit) {
MongoCollection<Document> doc = getColl(coll);
//排序
Bson orderBy = new BasicDBObject("_id", 1);
FindIterable<Document> docfilter = params==null?doc.find():doc.find(params);
return docfilter.sort(orderBy).skip((page - 1) * page).limit(limit).iterator();
}
/**
*
@param clazz 对象类型
@param filter 过滤条件,如:Filters.eq("name", "张三")
@param page
@param limit
@return
*/
public <T> List<T> queryByPage(Class<T> clazz,Bson filter, int page, int limit) {
MongoCollection<Document> doc = getColl(getClazzName(clazz));
//排序
Bson orderBy = new BasicDBObject("_id", 1);
FindIterable<Document> docfilter = filter==null?doc.find():doc.find(filter);
MongoCursor<Document> result = docfilter.sort(orderBy).skip((page - 1) * page).limit(limit).iterator();
List<T> list = new ArrayList<T>();
while(result.hasNext()) {
JSONObject json = JSON.parseObject(result.next().toJson());
json.remove("_id");
T item = JSON.toJavaObject(json, clazz);
list.add(item);
}
return list;
}
/**
*
@param clazz 对象类型
@param filter 过滤条件,如:filter = Filters.eq("name", "张三")
@param orderBy 排序,如:orderBy = new BasicDBObject("date", 1);1升序,-1表示倒序
@param page
@param limit
@return
*/
public <T> List<T> queryByPage(Class<T> clazz,Bson filter,Bson orderBy, int page, int limit) {
MongoCollection<Document> doc = getColl(getClazzName(clazz));
//排序
if(orderBy==null) {
orderBy = new BasicDBObject("_id", 1);
}
FindIterable<Document> docfilter = filter==null?doc.find():doc.find(filter);
MongoCursor<Document> result = docfilter.sort(orderBy).skip((page - 1) * page).limit(limit).iterator();
List<T> list = new ArrayList<T>();
while(result.hasNext()) {
JSONObject json = JSON.parseObject(result.next().toJson());
json.remove("_id");
T item = JSON.toJavaObject(json, clazz);
list.add(item);
}
return list;
}
/**
* 查询所有数据
@param clazz 对象类型
@param filter 过滤条件,如:Filters.eq("name", "张三")
@return
*/
@SuppressWarnings("hiding")
public <T> List<T> queryAllList(Class<T> clazz,Bson filter) {
MongoCollection<Document> doc = getColl(getClazzName(clazz));
//排序
Bson orderBy = new BasicDBObject("_id", 1);
FindIterable<Document> docfilter = filter==null?doc.find():doc.find(filter);
MongoCursor<Document> result = docfilter.sort(orderBy).iterator();
List<T> list = new ArrayList<T>();
while(result.hasNext()) {
JSONObject json = JSON.parseObject(result.next().toJson());
json.remove("_id");
T item = JSON.toJavaObject(json, clazz);
list.add(item);
}
return list;
}
/**
* 统计总数
* @param coll 集合名
*/
public long count(String coll) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
return doc.countDocuments();
}
/**
* 统计总数
@param clazz JavaBean类
@return
*/
public long count(Class<?> clazz) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(clazz));
return doc.countDocuments();
}
/**
* 根据条件查询数量
@param coll
@param params
@return
*/
public long count(String coll,BasicDBObject params) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
return doc.countDocuments(params);
}
/**
* 根据条件查询数量
@param clazz JavaBean类
@param params 参数
@return
*/
public long count(Class<?> clazz,BasicDBObject params) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(clazz));
return doc.countDocuments(params);
}
/**
* 修改一条数据
* @param coll 表名
* @param params 参数(类似于sql中的where条件)
* @param document 需要操作的文档对象
* <pre>
* //设置条件参数
* BasicDBObject params = new BasicDBObject("id", 5);
* //实例化修改对象:
* Document document = new Document();
* //添加修改内容:
* document.append("$set",new Document("sex","男"));
* </pre>
*/
public void update(String coll,BasicDBObject params,Document document) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
doc.updateOne(params,document);
}
/**
* 修改一条数据
*@param clazz JavaBean类
* @param params 参数(类似于sql中的where条件)
* @param document 需要操作的文档对象
* <pre>
* //设置条件参数
* BasicDBObject params = new BasicDBObject("id", 5);
* //实例化修改对象:
* Document document = new Document();
* //添加修改内容:
* document.append("$set",new Document("sex","男"));
* </pre>
*/
public void update(Class<?> clazz,BasicDBObject params,Document document) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(getClazzName(clazz));
doc.updateOne(params,document);
}
/**
* 修改多条数据
* @param coll 表名
* @param params 参数(类似于sql中的where条件)
* @param document 需要操作的文档对象
* <pre>
* 实例化修改对象:
* Document document = new Document();
* //添加修改内容:
* document.append("$set",new Document("sex","男"));
* </pre>
*/
public void updateMany(String coll,BasicDBObject params,Document document) {
//获取文档集合对象
MongoCollection<Document> doc = getColl(coll);
doc.updateMany(params,document);
}
/**
* 设置mongodb修改数据,通过反射获取javaBean的属性名和值
@param obj 数据对象
@param document 修改对象
@param filterField 需要过滤的字段,格式为javaBean实体属性名,多个用竖线|分隔,如:id|userPasswd
@return
*/
public Document updateSetFieldVal(Object obj,Document document,String filterField) {
if(obj==null) {return document;}
try {
//构造修改数据对象,mongodb修改数据命令为:db.news.update({'id':11},{$set:{'name':'111',"title":"标题"}},{multi:true})
Document doc = new Document();
for (Field field : obj.getClass().getDeclaredFields()) {
field.setAccessible(true);
Object value = field.get(obj);
Nullable nb = field.getAnnotation(Nullable.class);
//判断需要过滤的属性
if(filterField!=null && !"".equals(filterField)) {
String[] filterFields = filterField.split("\\|");
if(Arrays.asList(filterFields).contains(field.getName())) {
continue;
}
}
if(nb !=null) {
doc.append(field.getName(),value);
}else {
if (value!=null) {
doc.append(field.getName(),value);
}
}
}
document.append("$set",doc);
return document;
} catch (Exception e) {
e.printStackTrace();
System.out.println("对象属性为空异常" + e);
return document;
}
}
/**
*获取指定对象的类名,并将首字母转为小写
*/
private String getClazzName(Object obj) {
String clazzName = obj.getClass().getSimpleName();
String firstChar=clazzName.substring(0,1);
clazzName=clazzName.replaceFirst(firstChar, firstChar.toLowerCase());
return clazzName;
}
/**
*获取指定类的类名,并将首字母转为小写
*/
private String getClazzName(Class<?> clazz) {
String clazzName = clazz.getSimpleName();
String firstChar=clazzName.substring(0,1);
clazzName=clazzName.replaceFirst(firstChar, firstChar.toLowerCase());
return clazzName;
}
/**
*获取集合的第一个元素
*/
public static Object first(Object obj) {
if (null == obj)
return obj;
if (obj instanceof Collection<?>) {
Iterator<?> it = ((Collection<?>) obj).iterator();
return it.hasNext() ? it.next() : null;
}
if (obj.getClass().isArray())
return Array.getLength(obj) > 0 ? Array.get(obj, 0) : null;
return obj;
}
}
其中用到了:fastjson,hutool的BeanUtil等工具
测试一下:
public static void main(String[] args) {
MongodbHelper mongodbHelper = new MongodbHelper();
Map<String,Object> map = new HashMap<>();
map.put("id",100);
map.put("name","张三");
map.put("age",18);
map.put("stuNo", "2106050540000");
map.put("sex","女");
mongodbHelper.insertOne("userInfo", map);
FindIterable<Document> list = mongodbHelper.query("userInfo");
for(Document doc:list) {
System.out.println(doc);
}
/对象操作示例/
DemoData demoData = new DemoData();
demoData.setId(UUID.randomUUID().toString().replace("-", ""));
demoData.setCode("200");
demoData.setDate(LocalDateTime.now().toString());
demoData.setName("李四");
demoData.setDoubleData(2022)
//增加
mongodbHelper.insert(demoData);
//修改开始///
//实例化修改对象:
Document document = new Document();
//添加修改内容:
mongodbHelper.updateSetFieldVal(demoData, document, "id");
//执行修改
BasicDBObject params = new BasicDBObject("id", "682afe866bbf43e9bf4a62c8f3cdda7c");
mongodbHelper.update(DemoData.class, params, document);
//修改结束///
//查询
Bson param = Filters.eq("name", "张三");
List<DemoData> rslist = mongodbHelper.queryByPage(DemoData.class, param,1,5);
System.out.println(rslist);
}
DemoData实体类为:
package mongodb.demo;
import com.alibaba.fastjson.JSON;
public class DemoData {
private String id;
//标题
private String name;
//日期
private String date;
//数量
private int doubleData;
private String code;
public DemoData() {
super();
// TODO Auto-generated constructor stub
}
public DemoData(String id, String name, String date, int doubleData, String code) {
super();
this.id = id;
this.name = name;
this.date = date;
this.doubleData = doubleData;
this.code = code;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDate() {
return date;
}
public void setDate(String date) {
this.date = date;
}
public int getDoubleData() {
return doubleData;
}
public void setDoubleData(int doubleData) {
this.doubleData = doubleData;
}
@Override
public String toString() {
return JSON.toJSONString(this, true);
}
}