Basically what I want to achieve is a combination of:
Slick 3.0.0 database agnostism and Slick 3 reusable generic repository
I tried a lot, actually, but I can't get this to work at all.
abstract class BaseModel[T <: slick.lifted.AbstractTable[_]](query: TableQuery[T], val driver: JdbcProfile, val dbTableName: String)
{
lazy val all: TableQuery[T] = TableQuery[T]
import driver.api._
def createTable = all.schema.create
def dropTable = all.schema.create
abstract class BaseTable[B](val tag: Tag) extends Table[B](tag, dbTableName)
{
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
}
}
Now here we have a problem already:
def createTable = all.schema.create
and the same with dropTable...
-> schema
cannot be resolved here, although I import the driver before.
But an even bigger problem comes in when I subclass this:
Here is the code
class NodeModel(driver: JdbcProfile, dbTableName: String) extends BaseModel[NodeTable](TableQuery[NodeTable], driver, dbTableName) {
val dbDriver = driver
import dbDriver.api._
class NodeTable(tag: Tag) extends BaseTable[Node](tag)
{
override def * = id.? <> (Node, Node.unapply)
}
//lazy val all: TableQuery[NodeTable] = TableQuery[NodeTable]
def createTable: DBIO[Unit] = all.schema.create
def dropTable: DBIO[Unit] = all.schema.drop
def insert(node: Node) = all += node
}
This won't compile obviously because I cannot pass NodeTable
as T
, but gives an idea of what I want to achieve.
Do you have any idea how to solve this? I also tried with companion objects, moving the BaseTable
out of the BaseModel
and trying to load a simpleDriver
... but it looks like that functionality was removed from Slick in a recent version :(
Database agnostic and Code is highly reusable
I am using
Slick
withPlayframework
and this is how I achieved database agnostic and generic repository.Note that this work is inspired from Active Slick
I want to have basic crud operations like this to be defined on my
case class
. I should be able to docount
,update
,delete
andcreate
. I want to write the curd code just once and reuse it for ever.Here is the snippet which demonstrates this.
CrudActions.scala
Now lets get our
Entity
into picture. Note thatEntity
is nothing but our case classEntity
iscase class
on which we do crud operations. For locating our entity lets also haveId
in place.Id
is important for locating and operating an entity or record in the database. AlsoId
uniquely identities for entityEntityActionsLike.scala
Now lets implement these methods. For doing operations we need
Table
andTableQuery
. Lets say we havetable
andtableQuery
. The good about traits is we can declare a contract and leave the implementation details to subclasses or subtypesEntityActions.scala
ActiveRecord.scala
ModelContract.scala
How to Use
Sample.scala
Now we can do operations on
Dog
directly like thisThis implicit does the magic for us
You can also add
scheme
creation and dropping logic in EntityActions