2015-12-30 24 views
1

結束執行代碼我連接到MongoDB的使用下面的代碼:總是在開頭和方法

def insert() = { 

    val mc = new com.mongodb.MongoClient("localhost", 27017); 
    val db = mc.getDatabase("MyDb"); 

    //My insert code 

    mc.close(); 

    }            //> insert:()Unit 

我有多種方法打開和關閉連接。 能否行:

val mc = new com.mongodb.MongoClient("localhost", 27017); 
val db = mc.getDatabase("MyDb"); 
mc.close(); 

中提取,使他們在開頭和方法的結束隱式調用。 斯卡拉暗示迎合這種情況還是需要反思?

回答

2

一個常見的模式是使用一個呼叫按姓名法在那裏你可以通過一個接受DB,並做了它的功能。通過名稱方法可以方便創建客戶端等,並在其中執行代碼。

def withDB[A](block: DB => A): A = { 
    val mc = new com.mongodb.MongoClient("localhost", 27017); 
    val db = mc.getDatabase("MyDb"); 
    try block(db) finally mc.close() 
} 

並使用它:

def insert() = withDB { db => 
    // do something with `db` 
} 

然而,看看documentation說:

一個MongoDB的客戶端與內部連接池。對於大多數應用程序,您應該爲整個JVM提供一個MongoClient實例。

這使得上面的方法看起來像一個壞主意,假設這是你使用的版本。我可以肯定地看到一些併發問題試圖做到這一點,並打開了太多的連接。

但是,您可以遵循相同的模式,將連接創建填充到單例對象中。但是,當您的應用程序關閉時,您需要管理客戶端的關閉。

object Mongo { 
    lazy val mc = new com.mongodb.MongoClient("localhost", 27017); 
    lazy val db = mc.getDatabase("MyDb"); 

    def withDB[A](block: DB => A): A = block(db) 

    def close(): Unit = mc.close() 
} 
+0

我懷疑代碼的最後一部分能夠很好地工作。正確處理連接池,初始化,清理是一個涉及的過程。 –

0

相反implicits的,你可以做這樣的事情:

def mongoConn(ip:String, port:Int, dbName:String):(Database => Unit) => Unit = { 
    f => { 
     val mc = new com.mongodb.MongoClient(ip, port) 
     val db = mc.getDatabase(dbName) 

     f(db) 

     mc.close() 
    } 
    } 

    val conn = mongoConn("localhost", 27017, "MyDb") 

    conn(db => { 
    //insert code 
    }) 
2

可以定義例如執行一些「工作」功能的方法

def withMongoDb[T](work: DB => T): T = { 
    val mc = new com.mongodb.MongoClient("localhost", 27017) 
    // I don't actually know what type `db` is so I'm calling it `DB` 
    val db: DB = mc.getDatabase("MyDb") 

    try { work(db) } 
    finally { mc.close() } 
} 

然後你可以使用它像:

withMongoDb { db => 
    db.insert(...) 
    db.query(...) 
} 

這是一個類似的方法來一個在Slick, pre-3.0使用,即withSessionwithTransaction

現在,如果您實施了一些便利方法,例如

def insertStuff(values: Seq[Int])(implicit db: DB) = { 
    db.insert(values) 
} 

然後,你可以調用標記dbwithMongoDb呼叫隱式,有效地確保你永遠不小心調用insertStuff之外的塊。

withMongoDb { implicit db => 
    insertStuff(Seq(1,2,3,4)) 
} 

insertStuff(Seq(1,2,3,4)) // compile error