我使用以下代码连接到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();
被提取,以便在方法的开头和结尾隐式调用它们。 Scala是否暗示是为了满足这种情况还是需要反思?
答案 0 :(得分: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中使用的方法类似,即withSession
和withTransaction
。
现在,如果你实现了一些便利方法,例如
def insertStuff(values: Seq[Int])(implicit db: DB) = {
db.insert(values)
}
然后,您可以在db
来电中将withMongoDb
标记为隐含,有效地确保您不会在该区块之外不小心拨打insertStuff
。
withMongoDb { implicit db =>
insertStuff(Seq(1,2,3,4))
}
insertStuff(Seq(1,2,3,4)) // compile error
答案 1 :(得分:2)
一种常见的模式是使用按名称调用方法,您可以传递一个接受DB
的函数并对其执行某些操作。 call-by-name方法可以促进客户端等的创建,并在其中执行代码。
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()
}
答案 2 :(得分:0)
而不是暗示你可以做这样的事情:
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
})