1. 程式人生 > >MongoDB學習(六) Java原生使用MongoDB

MongoDB學習(六) Java原生使用MongoDB

額外,可以參考用一個第三方框架:BuguMongo,或者後面的兩篇文章中的orm.但是這個bugumongo是2014年的框架,後來沒有更新了

官方文件和原始碼均建議在Java中使用MongoClient來操作MongoDB,而且,在不久的將來,會廢棄Mongo類。

這裡是簡單的一個操作封裝

DAO介面

import java.util.List;
import org.bson.Document;
import org.bson.conversions.Bson;

public interface BaseMongoDao
{
  boolean insertOne(String paramString, Document paramDocument);

  void insertMany(String paramString, List<Document> paramList);

  void delete(String paramString, Document paramDocument);

  void deleteAll(String paramString);

  List<Document> queryByCondition(String paramString, MongoCondition paramMongoCondition);

  Document findByCondition(String paramString, MongoCondition paramMongoCondition);

  Document findByCondition(String paramString, Bson paramBson);

  Document findByConditionSkip(String paramString, MongoCondition paramMongoCondition, int paramInt);

  Document findByConditionSkip(String paramString, Bson paramBson, int paramInt);

  int count(String paramString, MongoCondition paramMongoCondition);

  boolean update(String paramString, Document paramDocument1, Document paramDocument2);

  Document findAndUpdate(String paramString, Document paramDocument1, Document paramDocument2);
}

DAO實現類

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.bson.Document;
import org.bson.conversions.Bson;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Repository;
import org.springframework.util.ObjectUtils;

import com.mongodb.BasicDBObject;
import com.mongodb.Bytes;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.MongoCredential;
import com.mongodb.ServerAddress;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.model.Filters;
import com.mongodb.client.result.UpdateResult;

@Repository
public class BaseMongoDaoImpl implements InitializingBean, BaseMongoDao {
	private static Logger logger = Logger.getLogger(BaseMongoDaoImpl.class);
	// mongo 客戶端
	private static MongoClient mongoClient;
	private static MongoDatabase mongoDB;

	@Value("${mongo.connect}")
	private String connect;
	@Value("${mongo.username}")
	private String username;
	@Value("${mongo.password}")
	private String password;
	@Value("${mongo.database}")
	private String database;
	private int poolSize;

	@Override
	public boolean insertOne(String collectionName, Document document) {
		try {
			mongoDB.getCollection(collectionName).insertOne(document);
			return true;
		} catch (Exception e) {
			logger.error(
					"collectionName:" + collectionName + "\n document:" + document.toJson() + " \n" + e.getMessage());
		}
		return false;
	}

	@Override
	public void insertMany(String collectionName, List<Document> documents) {
		try {
			mongoDB.getCollection(collectionName).insertMany(documents);
		} catch (Exception e) {
			logger.error("insertMany error . collectionName:" + collectionName + " \n" + e.getMessage());
		}
	}

	@Override
	public void delete(String collectionName, Document filter) {
		try {
			mongoDB.getCollection(collectionName).deleteMany(filter);
		} catch (Exception e) {
			logger.error("delete error. collectionName:" + collectionName + "\n document:" + filter.toJson() + " \n"
					+ e.getMessage());
		}
	}

	@Override
	public void deleteAll(String collectionName) {
		try {
			Document document = new Document();
			mongoDB.getCollection(collectionName).deleteMany(document);
		} catch (Exception e) {
			logger.error("delete error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
	}

	@Override
	public List<Document> queryByCondition(String collectionName, MongoCondition condition) {
		List<Document> objects = null;
		try {
			if (condition == null) {
				condition = new MongoCondition();
			}
			Collection<QueryItem> items = condition.getQueryItems();

			// 生成查詢條件
			Bson bson = createBsonByQueryItemList(items);
			// 按指定地段排序
			BasicDBObject sort = new BasicDBObject();
			if (!(StringUtils.isEmpty(condition.getOrderbyProperty()))) {
				if (condition.isDesc()) {
					sort.put(condition.getOrderbyProperty(), -1);
				} else {
					sort.put(condition.getOrderbyProperty(), 1);
				}
			} else {
				sort.put("_id", 1);
			}
			// 分頁
			int currentPage = condition.getCurrentPage();
			int pageSize = condition.getPageSize();
			if (pageSize < 0) {
				return null;
			}
			FindIterable<Document> iterable = null;
			if (bson == null) {
				iterable = mongoDB.getCollection(collectionName).find().sort(sort).skip((currentPage - 1) * pageSize)
						.limit(pageSize);
			} else {
				iterable = mongoDB.getCollection(collectionName).find(bson).sort(sort)
						.skip((currentPage - 1) * pageSize).limit(pageSize);
			}
			MongoCursor<Document> cursor = iterable.iterator();
			objects = new ArrayList<Document>();
			while (cursor.hasNext()) {
				Document document = cursor.next();
				objects.add(document);
			}
		} catch (Exception e) {
			logger.error("queryByCondition error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return objects;
	}

	@Override
	public Document findByCondition(String collectionName, MongoCondition condition) {
		Document object = null;
		try {
			if (condition == null) {
				condition = new MongoCondition();
			}
			Collection items = condition.getQueryItems();

			Bson bson = createBsonByQueryItemList(items);
			if (bson == null)
				object = (Document) mongoDB.getCollection(collectionName).find().first();
			else
				object = (Document) mongoDB.getCollection(collectionName).find(bson).first();
		} catch (Exception e) {
			logger.error("findByCondition error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return object;
	}

	@Override
	public Document findByCondition(String collectionName, Bson bson) {
		Document object = null;
		try {
			if (bson == null)
				object = (Document) mongoDB.getCollection(collectionName).find().first();
			else
				object = (Document) mongoDB.getCollection(collectionName).find(bson).first();
		} catch (Exception e) {
			logger.error("findByCondition error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return object;
	}

	@Override
	public Document findByConditionSkip(String collectionName, MongoCondition condition, int skip) {
		Document object = null;
		try {
			if (condition == null) {
				condition = new MongoCondition();
			}
			Collection<QueryItem> items = condition.getQueryItems();

			Bson bson = createBsonByQueryItemList(items);
			if (bson == null)
				object = (Document) mongoDB.getCollection(collectionName).find().skip(skip).first();
			else
				object = (Document) mongoDB.getCollection(collectionName).find(bson).skip(skip).first();
		} catch (Exception e) {
			logger.error("findByCondition error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return object;
	}

	@Override
	public Document findByConditionSkip(String collectionName, Bson bson, int skip) {
		Document object = null;
		try {
			if (bson == null)
				object = (Document) mongoDB.getCollection(collectionName).find().skip(skip).first();
			else
				object = (Document) mongoDB.getCollection(collectionName).find(bson).skip(skip).first();
		} catch (Exception e) {
			logger.error("findByCondition error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return object;
	}

	@Override
	public int count(String collectionName, MongoCondition condition) {
		int count = 0;
		try {
			if (condition == null) {
				condition = new MongoCondition();
			}
			Collection<QueryItem> items = condition.getQueryItems();

			Bson bson = createBsonByQueryItemList(items);
			if (bson == null)
				count = (int) mongoDB.getCollection(collectionName).count();
			else
				count = (int) mongoDB.getCollection(collectionName).count(bson);
		} catch (Exception e) {
			logger.error("count error. collectionName:" + collectionName + " \n" + e.getMessage());
		}
		return count;
	}

	@Override
	public boolean update(String collectionName, Document filter, Document update) {
		try {
			UpdateResult result = mongoDB.getCollection(collectionName).updateMany(filter,
					new Document("$set", update));

			return (result.getModifiedCount() > 0L);
		} catch (Exception e) {
			logger.error("update error. collectionName:" + collectionName + "\n filter:" + filter.toJson()
					+ "\n update:" + update.toJson() + " \n" + e.getMessage());
		}
		return false;
	}

	@Override
	public Document findAndUpdate(String collectionName, Document filter, Document update) {
		Document document = null;
		try {
			document = (Document) mongoDB.getCollection(collectionName).findOneAndUpdate(filter, update);
		} catch (Exception e) {
			logger.error("findAndUpdate error. collectionName:" + collectionName + "\n filter:" + filter.toJson()
					+ "\n update:" + update.toJson() + " \n" + e.getMessage());
		}
		return document;
	}

	@Override
	public void afterPropertiesSet() {
		try {
			if (mongoClient == null) {
				mongoClient = getMongoClient();
				mongoDB = mongoClient.getDatabase(database);
				logger.info("MongoDB connect to : " + connect + ":" + mongoDB.getName());
			}
		} catch (Exception e) {
			logger.error("get database " + database + " error .", e);
		}
	}
	
	//建立資料庫連線
	//連線池大小,MongoDB預設連線池10個連線,且執行緒安全,增刪改查自動建立連線,用完後自動釋放連線
	private MongoClient getMongoClient() {
		poolSize = ((poolSize <= 0) ? 10 : poolSize);
		try {
			if (StringUtils.isNotEmpty(connect)) {
				MongoClientOptions.Builder build = new MongoClientOptions.Builder();
				build.connectionsPerHost(poolSize);
				String[] hosts = connect.split(",");
				List<ServerAddress> addressList = new ArrayList<ServerAddress>();
				for (String h : hosts) {
					String[] path = h.split(":");
					if (path.length > 1) {
						addressList.add(new ServerAddress(path[0], Integer.parseInt(path[1])));
					} else {
						logger.error("invalidate config for mongodb :" + h);
						return null;
					}
				}
				if (addressList.size() == 0) {
					logger.error("invalidate mongo config , nothing to do : " + this.connect);
					return null;
				}
				if (!(StringUtils.isEmpty(username))) {// 有密碼配置
					List<MongoCredential> mongoCredentialList = new ArrayList<MongoCredential>();
					mongoCredentialList.add(MongoCredential.createCredential(username, database, password.toCharArray()));
					mongoClient = new MongoClient(addressList, mongoCredentialList);
				} else {//無密碼
					mongoClient = new MongoClient(addressList);
				}
				mongoClient.addOption(Bytes.QUERYOPTION_SLAVEOK);
			}
		} catch (Exception e) {
			logger.error("getMongoClient error ", e);
		}
		return mongoClient;
	}

	//建立並格式化查詢條件
	private Bson createBsonByQueryItemList(Collection<QueryItem> items) {
		Bson bson = null;
		try {
			List listC = new ArrayList();
			if ((null != items) && (!(items.isEmpty()))) {
				for (QueryItem item : items) {
					if (null == item) {
						continue;
					}
					if (item.getFormula() == Formula.EQ) {
						listC.add(Filters.eq(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.LIKE) {
						listC.add(Filters.regex(item.getParam(), Pattern.compile("^.*" + item.getValue() + ".*$", 2)));
					} else if (item.getFormula() == Formula.IN) {
						if (ObjectUtils.isArray(item.getValue())) {
							Object[] values = (Object[]) (Object[]) item.getValue();
							listC.add(Filters.in(item.getParam(), values));
						} else if (item.getValue() instanceof List) {
							listC.add(Filters.in(item.getParam(), ((List) item.getValue()).toArray()));
						} else {
							listC.add(Filters.in(item.getParam(), new Object[] { item.getValue() }));
						}
					} else if (item.getFormula() == Formula.GE) {
						listC.add(Filters.gte(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.LE) {
						listC.add(Filters.lte(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.GT) {
						listC.add(Filters.gt(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.LT) {
						listC.add(Filters.lt(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.NE) {
						listC.add(Filters.ne(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.IS) {
						listC.add(Filters.eq(item.getParam(), item.getValue()));
					} else if (item.getFormula() == Formula.BETWEEN) {
						Object params = item.getValue();
						if ((params != null) && (ObjectUtils.isArray(params))) {
							Object[] array = (Object[]) (Object[]) params;
							listC.add(Filters.gte(item.getParam(), array[0]));
							listC.add(Filters.lte(item.getParam(), array[1]));
						}
					}
				}
				if (listC.size() > 0)
					bson = Filters.and(listC);
			}
		} catch (Exception localException) {
		}
		return bson;
	}

	public String getConnect() {
		return this.connect;
	}

	public void setConnect(String connect) {
		this.connect = connect;
	}

	public String getUser() {
		return this.username;
	}

	public void setUser(String username) {
		this.username = username;
	}

	public String getPassword() {
		return this.password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getDatabase() {
		return this.database;
	}

	public void setDatabase(String database) {
		this.database = database;
	}

	public int getPoolSize() {
		return this.poolSize;
	}

	public void setPoolSize(int poolSize) {
		this.poolSize = poolSize;
	}
}
Formula
public enum Formula
{
  EQ,  //==
  NE,  //<>
  LT,  //<
  GT,  //>
  LE,  //<=
  GE,  //>=
  LIKE,  //like
  IN,  //in
  BETWEEN,  //between a and b
  IS,  //is a value null or not null
  OR  //or
}

MongoCondition.java

import java.io.Serializable;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Map;

public class MongoCondition implements Serializable {
	
	private static final long serialVersionUID = -5427500692306190991L;
	private Collection<QueryItem> queryItems = new LinkedHashSet<QueryItem>();
	private String orderbyProperty;
	private boolean desc = true; //預設為降序
	private int currentPage = 1;
	private int pageSize = 100;
	private String hint;
	//查詢結果需要排除的欄位 excludeFields和includeFields互斥,只能二選一
	private Collection<String> excludeFields = new LinkedHashSet<String>();
	private Collection<String> includeFields = new LinkedHashSet<String>();

	public Collection<QueryItem> getQueryItems() {
		return this.queryItems;
	}

	public int getCurrentPage() {
		return this.currentPage;
	}

	public void setCurrentPage(int currentPage) {
		this.currentPage = currentPage;
	}

	public int getPageSize() {
		return this.pageSize;
	}

	public void setPageSize(int pageSize) {
		this.pageSize = pageSize;
	}

	public String getOrderbyProperty() {
		return this.orderbyProperty;
	}

	public boolean isDesc() {
		return this.desc;
	}

	public void setDesc(boolean desc) {
		this.desc = desc;
	}

	public void setOrderbyProperty(String orderbyProperty) {
		this.orderbyProperty = orderbyProperty;
	}

	public MongoCondition setOrderby(String orderProperty, boolean isAsc) {
		this.orderbyProperty = orderProperty;
		setDesc(!(isAsc));
		return this;
	}

	public MongoCondition addItem(QueryItem item) {
		this.queryItems.add(item);
		return this;
	}

	public MongoCondition addItem(String param, Object value, Formula formula) {
		this.queryItems.add(new QueryItem(param, value, formula));
		return this;
	}

	public MongoCondition addAll(Collection<QueryItem> items) {
		this.queryItems.addAll(items);
		return this;
	}

	public Collection<String> getExcludeFields() {
		return this.excludeFields;
	}

	public void addExcludeFields(String excludeField) {
		this.excludeFields.add(excludeField);
	}

	public void addIncludeFields(String includeField) {
		this.includeFields.add(includeField);
	}

	public Collection<String> getIncludeFields() {
		return this.includeFields;
	}

	public Map<String, Integer> getFields() {
		Map<String, Integer> includeMap = new HashMap();
		Map<String, Integer> excludeMap = new HashMap();

		// 限定排除
		if (this.excludeFields.size() > 0)
			for (String tmp : excludeFields) {
				excludeMap.put(tmp, 0);
			}
		if (this.includeFields.size() > 0) {
			for (String tmp : includeFields) {
				includeMap.put(tmp, 1);
			}
		}

		if (this.includeFields.size() > 0)
			return includeMap;
		if (this.excludeFields.size() > 0) {
			return excludeMap;
		}
		return null;
	}

	public String getHint() {
		return this.hint;
	}

	public void setHint(String hint) {
		this.hint = hint;
	}

	public String toString() {
		return "MongoCondition [queryItems=" + this.queryItems + ", orderbyProperty=" + this.orderbyProperty + ", desc="
				+ this.desc + ", currentPage=" + this.currentPage + ", pageSize=" + this.pageSize + ", hint="
				+ this.hint + ", excludeFields=" + this.excludeFields + ", includeFields=" + this.includeFields + "]";
	}
}

QueryItem.java

import java.io.Serializable;

public class QueryItem implements Serializable {
	private static final long serialVersionUID = 3207267704417597387L;
	private String param;
	private Object value;
	private Object start;
	private Object end;
	private Formula formula;
	private boolean ignoreCase = false;

	public QueryItem() {
	}

	public QueryItem(String param, Object value, Formula formula) {
		this.param = param;
		this.value = value;
		this.formula = formula;
	}

	public String getParam() {
		return this.param;
	}

	public void setParam(String param) {
		this.param = param;
	}

	public Object getValue() {
		return this.value;
	}

	public void setValue(Object value) {
		this.value = value;
	}

	public Object getStart() {
		return this.start;
	}

	public void setStart(Object start) {
		this.start = start;
	}

	public Object getEnd() {
		return this.end;
	}

	public void setEnd(Object end) {
		this.end = end;
	}

	public Formula getFormula() {
		return this.formula;
	}

	public void setFormula(Formula formula) {
		this.formula = formula;
	}

	public boolean isIgnoreCase() {
		return this.ignoreCase;
	}

	public void setIgnoreCase(boolean ignoreCase) {
		this.ignoreCase = ignoreCase;
	}

	public String toString() {
		return "{param:" + this.param + ",formula:" + this.formula + ",value:" + this.value + "}";
	}

	public int hashCode() {
		int prime = 31;
		int result = 1;
		result = 31 * result + ((this.end == null) ? 0 : this.end.hashCode());
		result = 31 * result + ((this.formula == null) ? 0 : this.formula.hashCode());
		result = 31 * result + ((this.ignoreCase) ? 1231 : 1237);
		result = 31 * result + ((this.param == null) ? 0 : this.param.hashCode());
		result = 31 * result + ((this.start == null) ? 0 : this.start.hashCode());
		result = 31 * result + ((this.value == null) ? 0 : this.value.hashCode());
		return result;
	}

	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (super.getClass() != obj.getClass())
			return false;
		QueryItem other = (QueryItem) obj;
		if (this.end == null)
			if (other.end != null)
				return false;
			else if (!(this.end.equals(other.end)))
				return false;
		if (this.formula != other.formula)
			return false;
		if (this.ignoreCase != other.ignoreCase)
			return false;
		if (this.param == null)
			if (other.param != null)
				return false;
			else if (!(this.param.equals(other.param)))
				return false;
		if (this.start == null)
			if (other.start != null)
				return false;
			else if (!(this.start.equals(other.start)))
				return false;
		if (this.value == null)
			if (other.value != null)
				return false;
			else if (!(this.value.equals(other.value)))
				return false;
		return true;
	}
}

測試用例:

import static org.junit.Assert.*;

import org.bson.Document;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;

import com.wqc.mongo.BaseMongoDao;
import com.wqc.mongo.Formula;
import com.wqc.mongo.MongoCondition;

/**   
 * @ClassName: JavaMongo   
 * @Description: TODO(這裡用一句話描述這個類的作用)   
 * @author:  
 * @date: 2018年5月30日 上午10:11:39    
 */

@RunWith(SpringJUnit4ClassRunner.class)  
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class JavaMongoTest {

	@Autowired
	public BaseMongoDao baseMongoDao;
	
	@Test
	public void test_01() {
		Document document = new Document();
		document.append("name", "張三");
		document.append("age", 18);
		document.append("mobile", "13866666666");
		baseMongoDao.insertOne("student", document);
	}
	
	@Test
	public void test_02() {
		MongoCondition mongoCondition = new MongoCondition();
		mongoCondition.addItem("name","張三",Formula.EQ);
		mongoCondition.addItem("age","18",Formula.EQ);
		mongoCondition.addItem("mobile","16888888888", Formula.EQ);
		Document document = baseMongoDao.findByCondition("student", mongoCondition);
		if (document != null) {
			System.out.println(document.toJson());
		}
		
	}

}

mongo.properties

mongo.database=mongodb
mongo.connect=127.0.0.1:27017
mongo.username=
mongo.password=