我正在使用Slick 1.0.1运行
Scala Play 2.2应用程序.我试图将所有数据库调用包装到将来的尝试中,例如:
object DbTeachers extends Table[DbTeacher]("edu_teachers") { ... def insertTeacher(school: Int,userId: String) (implicit ec: ExecutionContext,db: Database) = future { Try { db.withSession => { implicit s: Session => (DbTeachers.school ~ DbTeachers.teacher).insert(school,userId) }}} }
我发现模式未来{Try {db.withSession => {ACTUAL_CODE_GOES_HERE}}}会产生混乱,我想将其抽象如下:
sealed class DbAsync[T](block: => T) { import play.api.libs.concurrent.Execution.Implicits.defaultContext implicit lazy val db = Database.forDataSource(DB.getDataSource()) def get: Future[Try[T]] = future { Try { db.withSession { implicit s: Session => block }}} } object DbAsync { def apply[T](block: => T): Future[Try[T]] = new DbAsync[T](block).get }
然后我可以将insertTeacher函数编写为:
def insertTeacher(school: Int,userId: String) = DbAsync { (DbTeachers.school ~ DbTeachers.teacher).insert(school,userId) }
但是,scala编译器(2.10.2)抱怨这个:找不到参数会话的隐式值:scala.slick.session.Session
根据我的理解,insert()方法在DbAsync块中的范围内确实有一个隐式会话变量,并且因为它是一个按名称调用的参数,所以在DbAsync中调用它之前,它不应该被实际评估,此时在范围内会有一个隐式会话对象.
所以,我的问题是,如何说服Scala编译器在范围内实际存在隐式Session对象?
解决方法
你的建议不正确.在哪里评估call-by-name参数并不重要.所有隐式参数都应在编译时在需要它们的地方解析.
你可以这样工作:
def dbAsync[T](block: Session => T): Future[Try[T]] = { import play.api.libs.concurrent.Execution.Implicits.defaultContext implicit lazy val db = Database.forDataSource(DB.getDataSource()) future { Try { db.withSession { block }}} } def insertTeacher(school: Int,userId: String) = dbAsync { implicit s: Session => (DbTeachers.school ~ DbTeachers.teacher).insert(school,userId) }
请注意,您不需要类DbAsync也不需要对象DbAsync.
请注意,不应使用defaultContext进行阻止操作.您可以使用配置的线程池创建其他ExecutionContext.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。