在我们的项目中,我们始终在bean对象中注入dbConfigProvider: DatabaseConfigProvider
,然后使用db.run(some query)
进行数据库操作,它返回Future。如何为db.run
编写日志包装器,它将打印所有sql异常。
示例:
class SomeBeanImpl @Inject()(dbConfigProvider: DatabaseConfigProvider) {
private val logger = Logger(getClass)
def someDBQuery() = {
db.run(some wrong sql query) // exception raised in future, I need to print it with logger
}
}
注意:
如果我在每个.onFailure
电话上添加db.run
,那么我的代码会非常糟糕。这就是我需要为所有db.run
次调用编写此包装器的原因。
如果我将db.run
包含在具有不同签名的某个函数中,我必须在很多地方更改它,这不是最好的选择。我怎么能隐含地做到这一点?
答案 0 :(得分:1)
您不需要显式创建新的包装类,您可以使用Pimp My Library模式创建一个隐式方法,该方法包装db.run
的调用并附加onFailure
Future
:
object MyExtensions {
class DbExtensions(db: Db) {
def runAndLog(query: String): Future[String] = {
val result = db.run(query)
result.onFailure {
case e => Logger.getLogger("x").error(s"Exception: $e")
}
result
}
}
implicit def dbExtention(db: Db): DbExtensions = new DbExtensions(db)
}
class Db {
def run(query: String): Future[String] = Future.successful("Hello")
}
object App extends Application {
import MyExtensions._
val db = new Db
db.runAndLog("hello")
}
对于Scala 2.10及更高版本,使用Implicit Classes:
可以显着缩短这一点implicit class DbExtensions(val db: Db) {
def runAndLog(query: String): Future[String] = {
val result = db.run(query)
result.onFailure {
case e => Logger.getLogger("x").error(s"Exception: $e")
}
result
}
}
class Db {
def run(query: String): Future[String] = Future.successful("Hello")
}
object App extends Application {
val db = new Db
db.runAndLog("hello")
}
您可以进一步DbExtensions
扩展AnyVal
以进行效果优化:
implicit class DbExtensions(val db: Db) extends AnyVal
答案 1 :(得分:-1)
创建一个新课程:
case class DBWrapper(db: DatabaseComponent) {
def run(query: String) = db.run(query).onFailure { case e => logger.error(e) }
}
并使用db
将DBWrapper(db)
替换为初始化的Id
。
你也可以隐式地来回转换,虽然在这种情况下我不推荐它。