I am experiencing issues making Slick's TableQuery used in a generic fashion.
Observe the regular situation:
class AccountRepository {
override protected val dbConfig = DatabaseConfigProvider.get[JdbcProfile](Play.current)
val accounts = TableQuery[Accounts]
def all = db.run(accounts.result)
...
The idea would be to extract everything possible into generic trait or abstract class in order to avoid repetition. For the sake of simplicity I included only the problematic code.
abstract class GenericRepository[T] extends HasDatabaseConfig[JdbcProfile] {
override protected val dbConfig = DatabaseConfigProvider.get[JdbcProfile(Play.current)
val table = TableQuery[T]
}
And to use it like:
class AccountRepository extends GenericRepository[Accounts] {
However, that creates a compilation error:
type arguments [T] conform to the bounds of none of the overloaded alternatives of value apply: [E <: slick.lifted.AbstractTable[]]=> slick.lifted.TableQuery[E] [E <: slick.lifted.AbstractTable[]](cons: slick.lifted.Tag => E)slick.lifted.TableQuery[E]
Trying to fix the issue by setting a boundary doesn't help as well.
abstract class GenericRepository[T <: slick.lifted.AbstractTable[T]] extends HasDatabaseConfig[JdbcProfile] {
However, we end up with a different error:
class type required but T found
at following place:
val table = TableQuery[T]
Any idea about the solution?
You have to pass table query manually,
and in implementation,
I hope this will solve your problem.
I guess if you can solve the initialization of tableQuery, then you can continue your GenericRepository. I am using Slick 3.0 with PostgreSQL.
In the
slick.lifted.TableQuery
, there is a method like the followingSo if we can get an
instance of E
on the fly, then we can get a generic way to create TableQuery. So reflection seems to be a possible way to solve it.The codes mentioned above is just focused on the issue of generic TableQuery, try to combine it with your GenericRepository and your problem may get solved.
Anyway, hope it helps.