首先列一下WriteConcern的幾種拋出異常的級別參數:
當我們執行如下操作時(shí)(將"name"為"lily"的"age"設置為20):
db.update({"name":"lily"},{"$set":{"age":20}})默認情況下,該操作會(huì )使用WriteConcern.NORMAL(僅在網(wǎng)絡(luò )錯誤時(shí)拋出異常),等同于:
db.update({"name":"lily"},{"$set":{"age":20}},WriteConcern.NORMAL)使用NORMAL模式參數,可以使得寫(xiě)操作效率非常高。但是如果此時(shí)服務(wù)器出錯,也不會(huì )返回錯誤給客戶(hù)端,而客戶(hù)端會(huì )誤認為操作成功。
因此在很多重要寫(xiě)操作中需要使用WriteConcern.SAFE模式,保證可以感知到這個(gè)錯誤,保證客戶(hù)端和服務(wù)器對一次操作的正確性認知保持一致。
(根據筆者測試,如果服務(wù)器發(fā)生掉電情況,客戶(hù)端依然得不到當時(shí)操作的錯誤返回,需要特別注意)
另外在很多時(shí)候,我們需要確切知道這次寫(xiě)操作是否成功(或者本次更新操作影響了多少個(gè)對象),這時(shí)候就需要:
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});if(ret.getN()>0) //操作影響的對象個(gè)數 return true;else return false;或者:
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});if(ret.getLastError() == null) return true;else return false;此時(shí),getLastError()會(huì )查詢(xún)上次操作結果是否出現錯誤。
更進(jìn)一步
然后由于mongodb中使用連接池的原因,getLastError()需要再次從連接池中獲取連接,這樣效率會(huì )慢一些??梢赃@樣做:
db.requestStart();WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});if(ret.getLastError() == null) return true;else return false;db.requestDone();就可以保證update操作和getLastError()使用同一個(gè)連接,并且減少了一次存/取連接的過(guò)程。
還有一個(gè)方法
此時(shí)也可以使用WriteConcern.SAFE參數:
WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}}, WriteConcern.SAFE);if(ret.getLastError() == null) return true;else return false;// is equivalent to db.requestStart();WriteResult ret = db.update({"name":"lily"},{"$set":{"age":20}});if(ret.getLastError() == null) return true;else return false;db.requestDone();這也是我推薦使用的方式,這樣即可以高效的得到返回結果,還能感知到服務(wù)器錯誤,一舉兩得。
聯(lián)系客服