MongoDB Java Driver 源碼分析(7):com.mongodb.DBAPILayer
Posted on 2012-04-15 16:27 zljpp 閱讀(199) 評論(0) 編輯 收藏
DBAPILayer 繼承了抽象類 DB ,主要借助內(nèi)部類 DBApiLayer.MyCollection 實(shí)現(xiàn)具體的數(shù)據(jù)庫操作。
DB 類的介紹可以參考:http://xxing22657-yahoo-com-cn.iteye.com/blog/1291183
DBApiLayer.MyCollection 繼承了抽象類 DBCollection,具體實(shí)現(xiàn)了增刪改查操作。
DBCollection 類的介紹可以參考之前的文章:http://xxing22657-yahoo-com-cn.iteye.com/blog/1255181
增刪改查操作的方法聲明如下:
這些操作都需要借助 DBTCPConnector 的 say 方法和 call 方法,這兩個方法的實(shí)現(xiàn)可以參考這篇文章:
http://xxing22657-yahoo-com-cn.iteye.com/blog/1416331
下面以 insert 和 _find 操作為例進(jìn)行分析
DBApiLayer.MyCollection._find 方法返回的是 Result 對象,它實(shí)現(xiàn)了 Iterator 接口,可以用于遍歷。
next 方法和 hasNext 中都用到了 _advance 方法
DB 類的介紹可以參考:http://xxing22657-yahoo-com-cn.iteye.com/blog/1291183
借助 DBApiLayer.MyCollection 實(shí)現(xiàn)增刪改查
DBApiLayer.MyCollection 繼承了抽象類 DBCollection,具體實(shí)現(xiàn)了增刪改查操作。
DBCollection 類的介紹可以參考之前的文章:http://xxing22657-yahoo-com-cn.iteye.com/blog/1255181
增刪改查操作的方法聲明如下:
// 插入操作 protected WriteResult insert(DBObject[] arr, boolean shouldApply , com.mongodb.WriteConcern concern ) // 刪除操作 public WriteResult remove( DBObject o , com.mongodb.WriteConcern concern ) // 查找操作 Iterator<DBObject> __find( DBObject ref , DBObject fields , int numToSkip , int batchSize, int limit , int options ) // 更新操作 public WriteResult update( DBObject query , DBObject o , boolean upsert , boolean multi , com.mongodb.WriteConcern concern )
這些操作都需要借助 DBTCPConnector 的 say 方法和 call 方法,這兩個方法的實(shí)現(xiàn)可以參考這篇文章:
http://xxing22657-yahoo-com-cn.iteye.com/blog/1416331
下面以 insert 和 _find 操作為例進(jìn)行分析
// 插入操作 protected WriteResult insert(DBObject[] arr, boolean shouldApply , com.mongodb.WriteConcern concern ) throws MongoException { // 輸出跟蹤信息 if ( willTrace() ) { for (DBObject o : arr) { trace( "save: " + _fullNameSpace + " " + JSON.serialize( o ) ); } } // 是否更新對應(yīng)的DBObject if ( shouldApply ){ for ( int i=0; i<arr.length; i++ ){ DBObject o=arr[i]; apply( o ); _checkObject( o , false , false ); Object id = o.get( "_id" ); if ( id instanceof ObjectId ){ ((ObjectId)id).notNew(); } } } WriteResult last = null; // 輸出 DBObject 到 Mongo 服務(wù)器 int cur = 0; int maxsize = _mongo.getMaxBsonObjectSize(); while ( cur < arr.length ){ OutMessage om = new OutMessage( _mongo , 2002 ); // 以 0 作為交互開始的信號 om.writeInt( 0 ); // reserved // 輸出完整的 namespace om.writeCString( _fullNameSpace ); // 將要輸出的對象寫入 OutMessage for ( ; cur<arr.length; cur++ ){ DBObject o = arr[cur]; om.putObject( o ); // 一次批量插入數(shù)據(jù)量的上限是 maxBsonObjectSize 的 4 倍 // 安全起見,這里使用 maxBsonObjectSize 的兩倍 if ( om.size() > 2 * maxsize ){ // 超出一次批量插入的限制 // 停止構(gòu)造 OutMessage,準(zhǔn)備進(jìn)入下一個循環(huán) cur++; break; } } // 調(diào)用 DBTCPConnector 的 say 方法執(zhí)行寫入 last = _connector.say( _db , om , concern ); } return last; } // 查找操作 Iterator<DBObject> __find( DBObject ref , DBObject fields , int numToSkip , int batchSize, int limit , int options ) throws MongoException { if ( ref == null ) ref = new BasicDBObject(); // 輸出跟蹤信息 if ( willTrace() ) trace( "find: " + _fullNameSpace + " " + JSON.serialize( ref ) ); // 構(gòu)造 OutMessage OutMessage query = OutMessage.query( _mongo , options , _fullNameSpace , numToSkip , chooseBatchSize(batchSize, limit, 0) , ref , fields ); // 調(diào)用 DBTCPConnector 的 call 方法獲得查詢結(jié)果 Response res = _connector.call( _db , this , query , null , 2 ); // 沒有結(jié)果 if ( res.size() == 0 ) return null; // 檢查錯誤 if ( res.size() == 1 ){ BSONObject foo = res.get(0); MongoException e = MongoException.parse( foo ); if ( e != null && ! _name.equals( "$cmd" ) ) throw e; } // 返回結(jié)果 return new Result( this , res , batchSize, limit , options ); }
借助 DBApiLayer.Result 遍歷結(jié)果
DBApiLayer.MyCollection._find 方法返回的是 Result 對象,它實(shí)現(xiàn)了 Iterator 接口,可以用于遍歷。
next 方法和 hasNext 中都用到了 _advance 方法
// 獲取下一條記錄 public DBObject next(){ // 當(dāng)前 cursor 有下一條記錄,直接返回 if ( _cur.hasNext() ) { return _cur.next(); } // 沒有結(jié)果,拋異常 if ( ! _curResult.hasGetMore( _options ) ) throw new RuntimeException( "no more" ); // 有結(jié)果,但不在當(dāng)前 cursor 中,取下一批數(shù)據(jù) _advance(); // 遞歸調(diào)用 return next(); } // 是否包含下一條記錄 public boolean hasNext(){ // 循環(huán)檢查 while ( true ){ // 當(dāng)前 cursor 有下一條記錄,直接返回 true if ( _cur.hasNext() ) return true; // 沒有結(jié)果,返回 false if ( ! _curResult.hasGetMore( _options ) ) return false; // 有結(jié)果,但不在當(dāng)前 cursor 中,取下一批數(shù)據(jù) _advance(); } } // 進(jìn)行到下一條記錄 private void _advance(){ if ( _curResult.cursor() <= 0 ) throw new RuntimeException( "can't advance a cursor <= 0" ); OutMessage m = new OutMessage( _mongo , 2005 ); // 以 0 作為交互開始的信號 m.writeInt( 0 ); // 輸出完整的 namespace m.writeCString( _collection._fullNameSpace ); // 輸出數(shù)據(jù)大小 m.writeInt( chooseBatchSize(_batchSize, _limit, _numFetched) ); // 輸出當(dāng)前 cusor 的位置 m.writeLong( _curResult.cursor() ); // 借助 DBTCPConnector 執(zhí)行讀取操作 Response res = _connector.call( DBApiLayer.this , _collection , m , _host ); // 讀取下一條 _numGetMores++; // 初始化 init( res ); }