始终在方法的开头和结尾执行代码
Always execute code at beginning and end of method
我正在使用以下代码连接到 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 隐式是否适合这种情况或是否需要反射?
你可以这样做而不是隐式:
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
})
您可以定义一个方法来执行某些 'work' 函数,例如
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
一种常见的模式是使用 call-by-name 方法,您可以在其中传递接受 DB
并对其执行某些操作的函数。 call-by-name方法可以方便创建client等,执行里面的代码
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 说:
A MongoDB client with internal connection pooling. For most applications, you should have one MongoClient instance for the entire JVM.
这使得上述方法看起来不是个好主意,假设这是您正在使用的版本。我肯定会看到一些并发问题,试图这样做并且打开了太多连接。
但是,您可以遵循相同的模式,将创建的连接填充到单例对象中。但是,当您的应用程序关闭时,您需要管理客户端的关闭。
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()
}
我正在使用以下代码连接到 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 隐式是否适合这种情况或是否需要反射?
你可以这样做而不是隐式:
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
})
您可以定义一个方法来执行某些 'work' 函数,例如
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
一种常见的模式是使用 call-by-name 方法,您可以在其中传递接受 DB
并对其执行某些操作的函数。 call-by-name方法可以方便创建client等,执行里面的代码
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 说:
A MongoDB client with internal connection pooling. For most applications, you should have one MongoClient instance for the entire JVM.
这使得上述方法看起来不是个好主意,假设这是您正在使用的版本。我肯定会看到一些并发问题,试图这样做并且打开了太多连接。
但是,您可以遵循相同的模式,将创建的连接填充到单例对象中。但是,当您的应用程序关闭时,您需要管理客户端的关闭。
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()
}