scala – Slick 3可重用的通用存储库
我遇到了使Slick的TableQuery以通用方式使用的问题.
观察常规情况: class AccountRepository { override protected val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current) val accounts = TableQuery[Accounts] def all = db.run(accounts.result) ... 我们的想法是将所有可能的内容提取到通用特征或抽象类中,以避免重复.为简单起见,我只包含有问题的代码. abstract class GenericRepository[T] extends HasDatabaseConfig[JdbcProfile] { override protected val dbConfig = DatabaseConfigProvider.get[JdbcProfile(Play.current) val table = TableQuery[T] } 并使用它像: class AccountRepository extends GenericRepository[Accounts] { 但是,这会产生编译错误:
尝试通过设置边界来解决问题也无济于事. abstract class GenericRepository[T <: slick.lifted.AbstractTable[T]] extends HasDatabaseConfig[JdbcProfile] { 但是,我们最终会遇到一个不同的错误:
在以下地方: val table = TableQuery[T] 有关解决方案的任何想法? 解决方法
我想如果你能解决tableQuery的初始化问题,那么你可以继续你的GenericRepository.我正在使用Slick 3.0和PostgreSQL.
在slick.lifted.TableQuery中,有一个类似如下的方法 // object TableQuery def apply[E <: AbstractTable[_]](cons: Tag => E): TableQuery[E] = new TableQuery[E](cons) 因此,如果我们可以动态获取E的实例,那么我们可以获得创建TableQuery的通用方法.所以反思似乎是解决它的可能方法. import scala.reflect.runtime.{ universe => ru } import slick.lifted.{ AbstractTable,ProvenShape,Tag } import slick.driver.PostgresDriver.api._ object Reflection { val runtimeMirror = ru.runtimeMirror(getClass.getClassLoader) def getTypeTag[T: ru.TypeTag] = ru.typeTag[T] def createClassByConstructor[T: ru.TypeTag](args: Any*) = runtimeMirror.reflectClass(getTypeTag[T].tpe.typeSymbol.asClass) .reflectConstructor(ru.typeOf[T].declaration(ru.nme.CONSTRUCTOR) .asMethod)(args: _*).asInstanceOf[T] } // context bound here is for createClassByConstructor to use abstract class GenericTableQuery[U,T <: AbstractTable[U]: ru.TypeTag] { import Reflection._ // look at following code: Students,if you want to initialize Students // you're gonna need a tag parameter,that's why we pass tag here val tableQuery = TableQuery.apply(tag => createClassByConstructor[T](tag)) } // Sample Table case class Student(name: String,age: Int) class Students(tag: Tag) extends Table[Student](tag,"students") { def name = column[String]("name") def age = column[Int]("age") override def * : ProvenShape[Student] = (name,age) <> (Student.tupled,Student.unapply _) } // get TableQuery object TestGenericTableQuery extends GenericTableQuery[Student,Students] { val studentQuery = tableQuery } 上面提到的代码只关注通用TableQuery的问题,尝试将它与GenericRepository结合起来,你的问题可能会得到解决. 无论如何,希望它有所帮助. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |