Java程序中與MongoDB建立連接~小記


1.Mongo和MongoClient的關系

MongoClient繼承自Mongo,使用Mongo也可建立連接,但是需要使用與Mongo適應的MongoOptions,MongoURI等類型。

2.建立連接

在MongoDB Java Driver API中,要操作MongoDB的第一步和使用其他DB Java Driver類似,都需要首先和數據庫建立連接。在MongoDBJava Driver API中,建立連接的類為com.mongodb.MongoClient.在討論連接字符串等內容之前,我們來看看它最簡單的使用方式:

MongoClient client = new MongoClient();

一個構造函數不帶任何參數的版本。使用這個構造函數連接到的是本地的MongoDB服務,即/127.0.0.1:27017,當然你如果改變了MongoDB服務的端口,那么這里顯示的端口就是你的端口了。

可以通過以下單元測試代碼進行驗證:

@Test  
public void testConstruactors() throws UnknownHostException {  
    MongoClient client;       
    client = new MongoClient();  
    //也可指定連接的Host:
    //client = new MongoClient("127.0.0.1");  
    assertEquals(new ServerAddress(), client.getAddress());  
    client.close();  
}  
3.設置連接的各項屬性
和其他DB Java Driver的連接一樣,MongoDB Java Driver的連接也提供了很多屬性,來一起了解其中幾個。要設置MongoClient有關連接的屬性,需要用到com.mongodb.MongoClientOpations類。這個類包含了 MongoClient建立連接時,與連接相關的所有屬性。該類提供了一Builder模式的方式創建並設置這些屬性的值。
MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).build();

分析上面的代碼,MongoClientOptions.Builder()得到的是一個MongoClientOptions的Builder,通過該Builder可以設置各種Options,例如connectionsPerHost(100),設置連接池中最大連接個數,需要注意的是,每個屬性的設置方法的返回類型是一個Builder,這意味着可以采用類似下面的鏈式調用

MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(100).threadsAllowedToBlockForConnectionMultiplier(200).build(); 
最后,當我們將需要的各項值設定好后,就調用Builder的builder()方法,得到一個MongoClientOptions對象。問題來了,上面的代碼只是為各項連接相關的屬性賦值,那如何將這些值交給MongoClient,讓它按照給出的屬性值來建立連接呢?
 
答案就是MongoClient的構造函數,如下所示:
MongoClientOptions customClientOptions = new MongoClientOptions.Builder().connectionsPerHost(50).maxWaitTime(2000).build();  
MongoOptions options = new MongoOptions(customClientOptions);  
client = new MongoClient("127.0.0.1", customClientOptions);  // 每個MongoClient實例維護一個連接池
assertEquals(new ServerAddress("127.0.0.1"), client.getAddress());  
assertEquals(options, client.getMongoOptions());  
client.close();  

MongoOptions options=new MongoOptions(customClientOptions):這行代碼並不影響MongoClientOptions的使用,只是展示如何獲取到設置的MongoClientOptions。

此外,也可直接通過MongoClient.getMongoOptions()獲取到MongoOptions后,進行設置,而不使用MongoClientOptions,如下

MongoOptions mps = mongoClient.getMongoOptions();  
mps.setConnectionsPerHost(mongoDBConfig.getPoolSize());  
mps.setConnectTimeout(mongoDBConfig.getConnectTimeout());  
mps.setMaxWaitTime(mongoDBConfig.getMaxWaitTime());  

通過兩種方式的對比,我更喜歡MongoClientOptions,代碼更加優雅。另外,即使沒有設置MongoClientOptions,MongoClient也會有默認的設置。

4.使用連接字符串進行連接
上面的連接只是指定了連接到MongoDB的服務,但是具體連接到哪個數據庫呢?使用什么樣的登錄名和密碼呢?這個時候就用到連接字符串了,我們先解釋下MongoDB的連接字符串,如下:
mongodb://[username:password@]host1[:port1][,host2[:port2],...[,hostN[:portN]]][/[database][?options]]

最簡單的連接字符串就是:mongodb://127.0.0.1

當然,在真正在項目開發中,沒人會這么用!!!!!!~~~回到主題,在MongoClient中,如何使用連接字符串進行連接呢?MongoDB Java Driver提供了一個 com.mongodb.MongoClientURI類型,使用方式如下:

client = new MongoClient(new MongoClientURI("mongodb://kwiner:test123@127.0.0.1/test?authMechanism=MONGODB-CR&maxPoolSize=500"));  
client.close();  

5.安全連接方式

MongoClient也提供了用戶名和密碼連接到指定數據庫的方式,需要用到com.mongodb.MongoCredential,該類在mongo-java-driver的2.11.0版本中才開始提供,請注意!

MongoClientOptions clientOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build();
List<MongoCredential> lstCredentials = Arrays.asList(MongoCredential.createMongoCRCredential("admin", "myinfo", "123456".toCharArray()));  
client = new MongoClient(new ServerAddress("127.0.0.1"),lstCredentials, clientOptions);  
client.close();  

或者

MongoClientOptions mongoOptions=new MongoClientOptions.Builder().connectionsPerHost(poolSize).threadsAllowedToBlockForConnectionMultiplier(200).build();
MongoClient mongoClient = new MongoClient(new ServerAddress(server, port), mongoOptions); // 每個MongoClient實例維護一個連接池
try {
db = mongoClient.getDatabase(database); collection = db.getCollection(table); catch (Exception e) {   mongoClient.close();   throw e; }
6.連接池
MongoClient本身就使用了連接池,如果我們使用了MongoClientOptions,則默認是100個連接
MongoClientOptions.Builder builder = new MongoClientOptions.Builder();  
MongoClientOptions options = builder.build();  
assertEquals(100, options.getConnectionsPerHost());//最大連接數  
assertEquals(0, options.getMinConnectionsPerHost());//最小連接數  
assertEquals(0, options.getMaxConnectionIdleTime());//連接的最大閑置時間  
assertEquals(0, options.getMaxConnectionLifeTime());//連接的最大生存時間  
assertEquals(120000, options.getMaxWaitTime());//最大等待可用連接的時間  
assertEquals(10000, options.getConnectTimeout());//連接超時時間  
  
MongoClient client = new MongoClient("127.0.0.1", customClientOptions);  
client.close();  
其中, 閑置時間和生存時間為0,表示無限制。
MongoClient的close方法會關閉底層連接,MongoClient的實例將變得不可用,應該根據程序的需要,適當的調用該方法,釋放資源。

7.連接副本集

使用MongoDB作為數據庫,基本上都會使用副本集,在這個集里面,有primary節點,又有其他secondary節點,並使用了讀寫分離,這個時候,使用java連接MongoDB服務應該怎么做呢? 其實很簡單,就是使用一個ServerAddress集合保存副本集中的所有節點,然后作為MongoClient的構造函數的參數,並使用ReadPreference設置讀寫策略,注意,ReadPreference的讀寫策略既可以在MongoClient上設置,作用與使用MongoClient連接的所有操作,也可以設置到每次具體的集合操作上,作用域該次操作。代碼如下:

在MongoClient上設置讀寫策略:

List<ServerAddress> addresses = new ArrayList<ServerAddress>();  
ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017);  
ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017);  
ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017);  
addresses.add(address1);  
addresses.add(address2);  
addresses.add(address3);  
  
mongoClient = new MongoClient(lstAddrs);  
mongoClient.setReadPreference(ReadPreference.primary()); 

在某次操作上設置讀寫策略:

List<ServerAddress> addresses = new ArrayList<ServerAddress>();  
ServerAddress address1 = new ServerAddress("192.168.1.136" , 27017);  
ServerAddress address2 = new ServerAddress("192.168.1.137" , 27017);  
ServerAddress address3 = new ServerAddress("192.168.1.138" , 27017);  
addresses.add(address1);  
addresses.add(address2);  
addresses.add(address3);  
   
MongoClient client = new MongoClient(addresses);  
DB db = client.getDB( "test" );  
DBCollection coll = db.getCollection( "test" );  
   
BasicDBObject object = new BasicDBObject();  
object.append( "test2" , "testval2" );  
   
//讀操作從副本節點讀取  
ReadPreference preference = ReadPreference.secondary();  
DBObject dbObject = coll.findOne(object, null , preference);  
System.out.println(dbObject);  

8.mongo連接池屬性設置

Mongo的實例其實就是一個數據庫連接池,這個連接池里默認有10個鏈接。我們沒有必要重新實現這個鏈接池,但是我們可以更改這個連接池的配置。因為Mongo的實例就是一個連接池,所以,項目中最好只存在一個Mongo的實例。

常見的配置參數:

connectionsPerHost:每個主機的連接數

threadsAllowedToBlockForConnectionMultiplier:線程隊列數,它以上面connectionsPerHost值相乘的結果就是線程隊列最大值。如果連接線程排滿了隊列就會拋出“Out of semaphores to get db”錯誤。

maxWaitTime:最大等待連接的線程阻塞時間

connectTimeout:連接超時的毫秒。0是默認和無限

socketTimeout:socket超時。0是默認和無限

autoConnectRetry:這個控制是否在一個連接時,系統會自動重試 

還有許多配置,可以參見mongodb的API。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM