1. 程式人生 > >java操作mongodb總結

java操作mongodb總結

新需求需要用到Mongodb去存APP過來的資料,所以就簡單學了一下。
專案是用Spring搭建的,本來直接用spring-data-mongodb這個模組就很簡單地實現操作mongodb的功能,但是,經理硬是不讓,必須使用mongodb原生的驅動去實現。給我挖坑。。。

一、mongodb介紹
說來mongodb和redis很像,非常像,記憶體資料庫,只是redis是以key-value形式儲存資料的,而mongodb可以像關係型資料庫一樣,建立資料庫,建表(mongodb叫做集合),然後往表中插入一條一條資料(mongodb叫做插入文件),這個是mongodb的基本概念。具體的百度一堆,不再贅述。

二、Java操作mongodb
首先假如mongodb的java驅動包

<dependency>
  <groupId>org.mongodb</groupId>
  <artifactId>mongo-java-driver</artifactId>
  <version>3.4.2</version>
</dependency>

接下來寫工具類,這裡注意,網上使用java操作mongodb的工具類寫法很多,絕大多數是使用mongo包下面的一些類,如DB、DBObject等,但是官方是推薦我們使用mongo/client包下面的類,如MongoClient,MongoCollection,MongoDatabase,Document等

首先說一下MongoClient,mongodb客戶端,本質其實就是一個數據庫連線池。這裡一定要注意,網上很多地方說,資料庫連線用完需要關閉,但是絕對不是將MongoClient.close()掉,把整個連線池都關閉,在併發環境下,影響可想而知,這裡我被深深的坑過。

MongoCollection,代表一個mongodb集合,也就是我們通常講的表。

MongoDatabase,資料庫,我們獲取資料連線時,需要事先指定是哪一個資料庫。

Document,文件,代表我們通常說的一條資料,注意,Mongodb資料是通過Bson格式儲存的,其實也是Json格式的變種。
說道Document,我們使用mongodb的原生驅動去操作時,最大的問題,也是最核心的東西,就是Document和Java Object之間的轉換

。為什麼網上說的很多工具類不推薦使用,那些工具類寫了等於白寫,比如,insert方法,直接傳遞一個Document方法,而Object如何轉成Document卻不說,當然,也有很多寫了這樣的轉換工具類,但是依然存在很多問題。

1、工具類寫法1

public  void insert(String collName,Object bean) throws JsonProcessingException {
     String json = jsonMapper.writeValueAsString(bean);
     Document doc = Document.parse(json);
     MongoCollection<Document> coll = getCollection(collName);
     coll.insertOne(doc);
 }

原理就是,將一切物件變成Json,再轉成Document,簡單,粗暴。但是很快就發現問題,日期型別,也就是Date型別資料,通過這樣的方式存進去之後變成了時間戳。要知道,mongodb裡面是有Date型別的,卻被強制轉換成時間戳,不明瞭。
當時,如果可以接受上面的形式,也行,但是,當你需要將這個長整型的資料,取出,變成Date()型別的時候,java虛擬機器表示不答應了,做不到,沒有辦法轉成date型別的資料,也正式因為這個原因,果斷放棄。

2、工具類寫法2
使用的mongo包下面的類

 public DBObject findOne(String collection, DBObject query, DBObject fields) {
        return db.getCollection(collection).findOne(query, fields);
  }

將Object需要通過這樣的方式變成DBObject。。。。。。。萬一是我們自定義的pojo,這麼寫,不噁心死,放棄。

DBObject dbObject2 = new BasicDBObject("username","insert2")  
            .append("age", 18)  
            .append("address", new BasicDBObject("province","陝西").append("city", "西安"))  
            .append("favourite", dbList2);  

3、目前比較靠譜的寫法。
首先,專案是Spring,所以,將工具類配成Bean,通過Spring來保證MongoClient是單例的。
準備,三個註解,通過註解,進行欄位反射,達到Document和Object之間的轉換,其實這就是spring-data-mongodb的原理
配置檔案:

#資料庫名稱
mongo.dbname = ak
#密碼
mongo.password = root
#使用者名稱
mongo.username = root
#主機#埠號
mongo.domains = 192.168.100.181:27017
#一個執行緒變為可用的最大阻塞數
mongo.connectionsPerHost= 300
#執行緒佇列數,它以上面connectionsPerHost值相乘的結果就是執行緒佇列最大值
mongo.threadsAllowedToBlockForConnectionMultiplier= 5000
#連線超時時間(毫秒
mongo.connectTimeout= 15000
#最大等待時間
mongo.maxWaitTime= 3000
#自動重連
mongo.autoConnectRetry= true
#scoket保持活動
mongo.socketKeepAlive= true
#scoket超時時間
mongo.socketTimeout=0

具體是什麼意思這些配置引數,百度一下。
接下來寫一個抽象的父類

/**
 * 建立一個會話實現對mongoDB的原子操作
 */
public abstract class AbstractMongoSession {
    private static MongoClient mongoClient = null;
    private Class<?> clazz;
    private MongoCollection<Document> collection;


    private  String domains;
    private  String user;
    private  String password;
    private  String database;
    private  int connectionsPerHost;
    private  int connectTimeout;
    private  int maxWaitTime;
    private  int socketTimeout;
    private  int threadsAllowedToBlockForConnectionMultiplier;

    public String getDomains() {
        return domains;
    }

    public void setDomains(String domains) {
        this.domains = domains;
    }

    public String getUser() {
        return user;
    }

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

    public String getPassword() {
        return password;
    }

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

    public String getDatabase() {
        return database;
    }

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

    public int getConnectionsPerHost() {
        return connectionsPerHost;
    }

    public void setConnectionsPerHost(int connectionsPerHost) {
        this.connectionsPerHost = connectionsPerHost;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setConnectTimeout(int connectTimeout) {
        this.connectTimeout = connectTimeout;
    }

    public int getMaxWaitTime() {
        return maxWaitTime;
    }

    public void setMaxWaitTime(int maxWaitTime) {
        this.maxWaitTime = maxWaitTime;
    }

    public int getSocketTimeout() {
        return socketTimeout;
    }

    public void setSocketTimeout(int socketTimeout) {
        this.socketTimeout = socketTimeout;
    }

    public int getThreadsAllowedToBlockForConnectionMultiplier() {
        return threadsAllowedToBlockForConnectionMultiplier;
    }

    public void setThreadsAllowedToBlockForConnectionMultiplier(int threadsAllowedToBlockForConnectionMultiplier) {
        this.threadsAllowedToBlockForConnectionMultiplier = threadsAllowedToBlockForConnectionMultiplier;
    }

    public MongoCollection<Document> getCollection() {
        return this.collection;
    }

    public Class<?> getClazz() {
        return clazz;
    }

    private  MongoDatabase getDB(){
        return getClient().getDatabase(database);
    }

    public  MongoCollection<Document> getCollection(String collName , Class<?> clazz){
        this.clazz = clazz;
        this.collection = getDB().getCollection(collName);
        return this.collection;
    }

    //初始化客戶端
    public  MongoClient getClient(){
        try {
            if(null != mongoClient){
                return mongoClient;
            }
            //組裝mongo服務端地址
            final List<ServerAddress> addressLists =new ArrayList<>();
            for(String domain : domains.split(";")){
                String[] hostAndPort = domain.split(":");
                String host = hostAndPort[0];
                String port = hostAndPort[1];
                ServerAddress serverAddress = new ServerAddress(host, Integer.parseInt(port));
                addressLists.add(serverAddress);
            }

            MongoClientOptions.Builder options = new MongoClientOptions.Builder();

            options.connectionsPerHost(connectionsPerHost);// 連線池設定為300個連線,預設為100
            options.connectTimeout(connectTimeout);// 連線超時,推薦>3000毫秒
            options.maxWaitTime(maxWaitTime); //
            options.socketTimeout(socketTimeout);// 套接字超時時間,0無限制
            options.threadsAllowedToBlockForConnectionMultiplier(threadsAllowedToBlockForConnectionMultiplier);// 執行緒佇列數,如果連線執行緒排滿了佇列就會丟擲“Out of semaphores to get db”錯誤。
            options.writeConcern(WriteConcern.SAFE);//

            final MongoClientOptions op = options.build();
            //組裝許可權物件
            final List<MongoCredential> credentialsLists = new ArrayList<>();
            MongoCredential credential = MongoCredential.createCredential(user, database, password.toCharArray());
            credentialsLists.add(credential);

            //建立客戶端
            mongoClient = new MongoClient(addressLists, credentialsLists, op);
        } catch (Exception e) {
           // logger.error("MongoDB init error",e);
        }
        return mongoClient;
    }


    /*
     * 儲存
     *
     * @param:實體
     *
     * @return:void
     */
    public abstract void save(String collName ,Object obj) throws Exception;

    public abstract void saveMany(List<Object> obj) throws Exception;

    // 刪除資料
    public abstract long delete(Object obj) throws Exception;

    public abstract long delete(Bson bson) throws Exception;

    // 刪除資料
    public abstract long deleteMany(List<Object> objs) throws Exception;

    public abstract long deleteMany(Bson bson);

    // 修改資料
    public abstract long upate(String collName ,Bson bson, Object obj) throws Exception;

    public abstract long update(Object obj) throws Exception;

    public abstract long upateMany(Bson bson, Object obj) throws Exception;

    public abstract long upateMany(Bson bson, List<Object> objs) throws Exception;

    public abstract long upateMany(List<Object> objs) throws Exception;

    // 查詢資料
    public abstract Object find(String collName ,Object obj) throws Exception;

    // 獲取所有的資料
    public abstract List<Object> finds(String collName  , Class<?> clazz) throws Exception;

    // 條件查詢資料
    public abstract List<Object> query(String collName ,Bson bson  , Class<?> clazz) throws Exception;

    public abstract Object queryOne(Bson bson) throws Exception;

    public abstract List<Object> query(Bson bson, Bson sort) throws Exception;

    public abstract Object queryOne(Bson bson, Bson sort) throws Exception;

    public abstract List<Object> query(Bson bson, Bson sort, int limit) throws Exception;

    public abstract List<Object> query(Bson bson, Bson sort, int limit, int skip) throws Exception;

    public abstract List<Object> query(Bson bson, Bson sort, Bson filter) throws Exception;

    public abstract Object queryOne(Bson bson, Bson sort, Bson Filter) throws Exception;

    public abstract long count();

    public abstract long count(Bson bson);


}

這個類寫的不怎麼好,還有優化的空間,但這裡暫不考慮。
接下來是實現類

/**
 * 建立一個會話實現對mongoDB的原子操作
 */
public class MongoSession extends AbstractMongoSession {


    public MongoSession() {
    }

    /**
     * 插入資料
     * @param collName 集合名稱
     * @param obj   集合對應的實體
     */
    @Override
    public void save(String collName , Object obj) throws Exception{

        this.getCollection(collName , obj.getClass()).insertOne(BsonUtil.toBson(obj));

    }

    /**
     * 刪除資料,未測試
     * @param obj
     * @return
     * @throws Exception
     */
    @Override
    public long delete(Object obj) throws Exception {

        DeleteResult result = this.getCollection().deleteOne(
                BsonUtil.toBson(obj));
        long count = result.getDeletedCount();
        return count;

    }

    /**
     * 未測試
     * @param obj
     */
    @Override
    public void saveMany(List<Object> obj) throws  Exception{

        this.getCollection().insertMany(BsonUtil.toBsons(obj));


    }

    /**
     * 未測試
     * @param bson
     * @return
     * @throws Exception
     */
    @Override
    public long delete(Bson bson) throws Exception {
        DeleteResult deleteResult = this.getCollection().deleteOne(bson);
        return deleteResult.getDeletedCount();
    }

    /**
     * 未測試
     * @param objs
     * @return
     */
    @Override
    public long deleteMany(List<Object> objs) throws Exception{
        List<Document> documents;
        int count = 0;

        documents = BsonUtil.toBsons(objs);
        for (int i = 0; null != documents && i < documents.size(); i++) {
            DeleteResult deleteResult = this.getCollection().deleteOne(
                    documents.get(i));
            count += deleteResult.getDeletedCount();
        }
        return count;

    }

    /**
     * 未測試
     * @param bson
     * @return
     */
    @Override
    public long deleteMany(Bson bson) {
        DeleteResult deleteResult = this.getCollection().deleteMany(bson);
        return deleteResult.getDeletedCount();
    }

    /**
     * 更新資料
     * @param collName 集合名稱
     * @param bson 條件
     * @param obj 集合對應實體
     * @return
     */
    @Override
    public long upate(String collName ,Bson bson, Object obj) throws Exception{

        UpdateResult result = this.getCollection(collName , obj.getClass()).updateOne(bson,
                new Document("$set", BsonUtil.toBson(obj)));
        return result.getMatchedCount();

    }

    /**
     * 未測試
     * @param obj
     * @return
     */
    @Override
    public long update(Object obj) throws Exception{
        Document document;

        document = BsonUtil.toBson(obj);
        Bson bson = Filters.eq("_id", document.get("_id"));
        UpdateResult updateResult = this.getCollection().updateOne(
                bson,
                new Document("$set", document));
        return updateResult.getMatchedCount();

    }

    /**
     * 未測試
     * @param bson
     * @param obj
     * @return
     */
    @Override
    public long upateMany(Bson bson, Object obj) throws Exception{

        UpdateResult updateResult = this.getCollection().updateMany(bson,
                new Document("$set", BsonUtil.toBson(obj)));
        return updateResult.getMatchedCount();

    }

    /**
     * 未測試
     * @param bson
     * @param obj
     * @return
     */
    @Override
    public long upateMany(Bson bson, List<Object> obj) throws Exception{
        for (int i = 0; null != obj && i < obj.size(); i++) {

            UpdateResult result = this.getCollection().updateMany(bson,
                    new Document("$set", BsonUtil.toBson(obj)));
            return result.getMatchedCount();

        }
        return 0;
    }

    /**
     * 未測試
     * @param objs
     * @return
     */
    @Override
    public long upateMany(List<Object> objs) throws Exception{
        long count = 0;
        for (int i = 0; null != objs && i < objs.size(); i++) {

            UpdateResult result = this.getCollection().updateMany(
                    Filters.eq("_id",
                            BsonUtil.toBson(objs.get(i)).get("_id")),
                    new Document("$set", BsonUtil.toBson(objs.get(i))));
            count += result.getMatchedCount();

        }
        return count;
    }

    /**
     *  按_id查詢
     * @param collName
     * @param obj
     * @return
     */
    @Override
    public Object find(String collName ,Object obj) throws Exception{

        Bson bson = Filters.eq("_id", new ObjectId(BsonUtil.toBson(obj).get("_id").toString()));
        Document document = this.getCollection(collName , obj.getClass())
                .find(bson)
                .first();
        return BsonUtil.toBean(document, this.getClazz());
    }

    /**
     * 查詢所有 , 未測試
     * @return
     */
    @Override
    public List<Object> finds(String collName , Class<?> clazz) throws Exception{
        FindIterable<Document> doIterable = this.getCollection(collName, clazz).find();
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();

            objects.add(BsonUtil.toBean(document, this.getClazz()));

        }
        return objects;
    }

    /**
     * 按條件查詢
     * @param collName
     * @param bson
     * @param clazz
     * @return
     */
    @Override
    public List<Object> query(String collName , Bson bson , Class<?> clazz) throws Exception{
        FindIterable<Document> doIterable = this.getCollection(collName , clazz).find(bson);
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();
            objects.add(BsonUtil.toBean(document, this.getClazz()));
        }
        return objects;
    }

    @Override
    public Object queryOne(Bson bson) throws Exception{
        Document document = this.getCollection().find(bson).first();

        return BsonUtil.toBean(document, this.getClazz());

    }

    @Override
    public List<Object> query(Bson bson, Bson sort) throws Exception{
        FindIterable<Document> doIterable = this.getCollection().find(bson)
                .sort(sort);
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();
            objects.add(BsonUtil.toBean(document, this.getClazz()));
        }
        return objects;
    }

    @Override
    public Object queryOne(Bson bson, Bson sort) throws Exception{
        Document document = this.getCollection().find(bson).sort(sort).first();

        return BsonUtil.toBean(document, this.getClazz());
    }

    @Override
    public List<Object> query(Bson bson, Bson sort, int limit) throws Exception{
        FindIterable<Document> doIterable = this.getCollection().find(bson)
                .sort(sort);
        if (limit > 0) {
            doIterable = doIterable.limit(limit);
        }
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();
            objects.add(BsonUtil.toBean(document, this.getClazz()));
        }
        return objects;
    }

    @Override
    public List<Object> query(Bson bson, Bson sort, int limit, int skip) throws Exception{
        FindIterable<Document> doIterable = this.getCollection().find(bson)
                .sort(sort);
        if (limit > 0) {
            doIterable = doIterable.limit(limit);
        }
        if (skip > 0) {
            doIterable = doIterable.skip(skip);
        }
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();
            objects.add(BsonUtil.toBean(document, this.getClazz()));
        }
        return objects;
    }

    @Override
    public List<Object> query(Bson bson, Bson sort, Bson filter) throws Exception{
        FindIterable<Document> doIterable = this.getCollection().find(bson)
                .sort(sort).filter(filter);
        MongoCursor<Document> cursor = doIterable.iterator();
        List<Object> objects = new ArrayList<Object>();
        while (cursor.hasNext()) {
            Document document = cursor.next();
            objects.add(BsonUtil.toBean(document, this.getClazz()));
        }
        return objects;
    }

    @Override
    public Object queryOne(Bson bson, Bson sort, Bson Filter) throws Exception{
        Document document = this.getCollection().find(bson).sort(sort)
                .filter(Filter).first();

        return BsonUtil.toBean(document, this.getClazz());

    }

    @Override
    public long count() {

        return this.getCollection().count();
    }

    @Override
    public long count(Bson bson) {
        // TODO Auto-generated method stub
        return this.getCollection().count(bson);
    }
}

當中有一些方法沒有用到,所以沒有做測試,可能存在問題。但也只是微調就可以了,比如將getCollection(),換成傳引數的那個getCollention。

注意到裡面有一個BsonUtil工具類,裡面就是實現Object和Document轉換的方法
在次之前,需要準備三個註解。分別代表,集合,列。

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface Table {
    public String name();

    public String text() default "表格對映";
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column {
    public String name();

    public String text() default "這是一個屬性對映";
}


@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotColumn {
    public String text() default "不是屬性欄位";
}

BenUtil工具類

/**
    工具類

**/
public class BsonUtil {
    public static <T> List<T> toBeans(List<Document> documents, Class<T> clazz)
            throws IllegalArgumentException, InstantiationException,
            IllegalAccessException, InvocationTargetException {
        List<T> list = new ArrayList<T>();
        for (int i = 0; null != documents && i < documents.size(); i++) {
            list.add(toBean(documents.get(i), clazz));
        }
        return list;
    }

    /*
     * 將Bson 轉化為物件
     *
     * @param:Bson文件
     *
     * @param:類pojo
     *
     * @param:返回物件
     */
    public static <T> T toBean(Document document, Class<T> clazz)
            throws InstantiationException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        T obj = clazz.newInstance();// 宣告一個物件
        Field[] fields = clazz.getDeclaredFields();// 獲取所有屬性
        Method[] methods = clazz.getMethods();// 獲取所有的方法
        /*
         * 查詢所有的屬性,並通過屬性名和資料庫欄位名通過相等對映
         */
        for (int i = 0; i < fields.length; i++) {
            String fieldName = fields[i].getName();
            Column column = fields[i].getAnnotation(Column.class);
            Object bson = null;
            if (null != column && null != column.name()) {
                bson = document.get(column.name());
            } else if ("id".equals(fieldName)) {
                bson = document.get("_id");
            } else {
                bson = document.get(fieldName);
            }
            if (null == bson) {
                continue;
            } else if (bson instanceof Document) {// 如果欄位是文件了遞迴呼叫
                bson = toBean((Document) bson, fields[i].getType());
            } else if (bson instanceof MongoCollection) {// 如果欄位是文件集了呼叫colTOList方法

                bson = colToList(bson, fields[i]);
            }
            for (int j = 0; j < methods.length; j++) {// 為物件賦值
                String metdName = methods[j].getName();
                if (equalFieldAndSet(fieldName, metdName)) {
                    methods[j].invoke(obj, bson);
                    break;
                }
            }
        }
        return obj;
    }

    public static List<Document> toBsons(List<Object> objs)
            throws IllegalArgumentException, SecurityException,
            IllegalAccessException, InvocationTargetException,
            NoSuchFieldException {
        List<Document> documents = new ArrayList<Document>();
        for (int i = 0; null != objs && i < objs.size(); i++) {
            documents.add(toBson(objs.get(i)));
        }
        return documents;
    }

    /*
     * 將物件轉化為Bson文件
     *
     * @param:物件
     *
     * @param:型別
     *
     * @return:文件
     */
    public static Document toBson(Object obj) throws IllegalArgumentException,
            IllegalAccessException, InvocationTargetException,
            SecurityException, NoSuchFieldException {
        if (null == obj) {
            return null;
        }
        Class<? extends Object> clazz = obj.getClass();
        Document document = new Document();
        Method[] methods = clazz.getDeclaredMethods();
        Field[] fields = clazz.getDeclaredFields();
        for (int i = 0; null != fields && i < fields.length; i++) {
            Column column = fields[i].getAnnotation(Column.class);// 獲取列註解內容
            NotColumn notColumn = fields[i].getAnnotation(NotColumn.class);// 獲取否列
            String key = null;// 對應的文件鍵值
            if (null != column && null != column.name()) {// 存在列對映取值
                key = column.name();
            } else if (null != notColumn) {// 不是列的情況
                continue;
            } else {
                key = fields[i].getName();// 預設情況通過屬性名對映
                if ("id".equals(key)) {// 替換id為_id
                    key = "_id";
                }
            }
            String fieldName = fields[i].getName();
            /*
             * 獲取物件屬性值並對映到Document中
             */
            for (int j = 0; null != methods && j < methods.length; j++) {
                String methdName = methods[j].getName();
                if (null != fieldName && equalFieldAndGet(fieldName, methdName)) {
                    Object val = methods[j].invoke(obj);// 得到值
                    if (null == val) {
                        continue;
                    }
                    if (isJavaClass(methods[j].getReturnType())) {
                        if (methods[j].getReturnType().getName()
                                .equals("java.util.List")) {// 列表處理
                            @SuppressWarnings("unchecked")
                            List<Object> list = (List<Object>) val;
                            List<Document> documents = new ArrayList<Document>();
                            for (Object obj1 : list) {
                                documents.add(toBson(obj1));
                            }
                            document.append(key, documents);
                        } else {// 其它物件處理,基本型別
                            document.append(key, val);
                        }
                    } else {// 自定義型別
                        document.append(key, toBson(val));
                    }
                }
            }
        }
        return document;
    }

    /*
     * 是否是自定義型別】
     *
     * false:是自定義
     */
    private static boolean isJavaClass(Class<?> clz) {
        return clz != null && clz.getClassLoader() == null;
    }

    /*
     * 將文件集轉化為列表
     *
     * @param:文件集
     *
     * @param:屬性型別
     *
     * @return:返回列表
     */
    private static List<Object> colToList(Object bson, Field field)
            throws InstantiationException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException {
        ParameterizedType pt = (ParameterizedType) field.getGenericType();// 獲取列表的型別
        List<Object> objs = new ArrayList<Object>();
        @SuppressWarnings("unchecked")
        MongoCollection<Document> cols = (MongoCollection<Document>) bson;
        MongoCursor<Document> cursor = cols.find().iterator();
        while (cursor.hasNext()) {
            Document child = cursor.next();
            @SuppressWarnings("rawtypes")
            Class clz = (Class) pt.getActualTypeArguments()[0];// 獲取元素型別
            @SuppressWarnings("unchecked")
            Object obj = toBean(child, clz);
            System.out.println(child);
            objs.add(obj);

        }
        return objs;
    }

    /*
     * 比較setter方法和屬性相等
     */
    private static boolean equalFieldAndSet(String field, String name) {
        if (name.toLowerCase().matches("set" + field.toLowerCase())) {
            return true;
        } else {
            return false;
        }
    }

    /*
     * 比較getter方法和屬性相等
     */
    private static boolean equalFieldAndGet(String field, String name) {
        if (name.toLowerCase().matches("get" + field.toLowerCase())) {
            return true;
        } else {
            return false;
        }
    }
}

到此,工具類大功告成。

4、使用方式
實體類

@Table(name = "GPSPOINT")
public class GPSPoint{


    /**
     * mongo id
     */
    @Column(name = "_id")
    private String _id;
    /**
     * 員工ID
     */
    @Column(name = "empId")
    private int empId;

    /**
     * 裝置型別
     */
    @Column(name = "deviceType")
    private int deviceType;

    /**
     * 高德GPS
     */
    @Column(name = "gdGps")
    private Point gdGps;

    /**
     * 百度GPS
     */
    @Column(name = "bdGps")
    private Point bdGps;

    /**
     * 時間
     */
    @Column(name = "time")
    private Date time;

    /**
     * 
     */
    @Column(name = "dealFlag")
    private int dealFlag;

    /**
     * 
     */
    @Column(name = "state")
    private int state;
//getset方法省略
}

實體類中,@Table註解指定了,這個實體對應的是mongodb中的那個表(集合),@Column表明這個欄位是一個mongodb的欄位,在BeanUtil工具類中,mongodb的欄位和Object欄位之間的對映關係就是通過這個註解實現,看程式碼就能看出來。

接下來,就是在Spring中配置一個bean

    <bean id="mongoSession" class="com.common.mongodb.MongoSession">
        <property name="domains" >
            <value>${mongo.domains}</value>
        </property>
        <property name="user">
            <value>${mongo.username}</value>
        </property>
        <property name="password">
            <value>${mongo.password}</value>
        </property>
        <property name="database">
            <value>${mongo.dbname}</value>
        </property>
        <property name="connectionsPerHost" value="${mongo.connectionsPerHost}"></property>
        <property name="connectTimeout" value="${mongo.connectTimeout}"></property>
        <property name="maxWaitTime" value="${mongo.maxWaitTime}"></property>
        <property name="socketTimeout" value="${mongo.socketTimeout}"></property>
        <property name="threadsAllowedToBlockForConnectionMultiplier" value="${mongo.threadsAllowedToBlockForConnectionMultiplier}"></property>
    </bean>

測試類就很簡單了

@Resource
private MongoSession mongoSession;

 @Test
 public void handl(){
        GPSPoint pointBo = new GPSPoint();
        pointBo.setEmpId(54321);
        pointBo.setDeviceType(0);
        pointBo.setGdGps(new Point("130.336122,140.118414"));
        pointBo.setDealFlag(1);
        pointBo.setState(1);
        pointBo.setTime(new Date());
        //插入
        mongoSession.save(pointBo);

        //更新
         Bson bson = Filters.eq("_id" , new ObjectId("58fec5b300300200f01cf9ab"));
         System.out.println(mongoSession.upate("GPSPoint" , bson , pointBo));


    //查詢
     Bson bson = Filters.eq("dealFlag" , 0);
      System.out.println(mongoSession.query(bson));
 }

總結
這個工具類,雖然也有缺陷,比較繁瑣,但是,使用起來比較方便。

注意
欄位不要用列舉型別,目前,我還沒看見有如果處理列舉型別的文章,spring-data-mongodb當前版本也不支援處理列舉型別,還是用簡單型別存放吧。