Slick Write simple table creation function

Um ... I tried Slick with Play 2. The process of creating a table became very upsetting, because unlike other ORMs (for example, ebean), Slick does not detect if the database was created, if there is already a table, it will report an exception. I just just don't want to drop and create every time I restart the server, so I decided to write a little function to help me:

def databaseCreate(tables: Table*) = { for (table <- tables) { if (MTable.getTables(table.getClass.getName).list.isEmpty) table.ddl.create } } 

What this means is to take some objects like this:

  object Tag extends Table [(Option[Int], String)]("Tags") { def id = column[Int]("TAG_ID", O.PrimaryKey, O.AutoInc) def tag_name = column[String]("TAG_NAME") def * = id.? ~ tag_name } 

And use the MTable method from scala.slick.jdbc.meta.MTable to find out if the table exists or not. Then I somehow ran into a simple Java reflection problem. If the databaseCreate method accepts rows, then I can call .ddl.create . So I decide to pass the objects and use the relfection: table.getClass.getName . The only problem is the type mismatch: (from my IDE)

Expected: MySQLDriver.simple.type # Table, current: BlogData.Tag.type

BlogData is a large object that I used to store all the small table objects. How to solve this problem of non-compliance? Use a whole bunch of asInstanceOf ? That would make the team unbearably long and ugly ...


Fixed:

Type mismatch is a false alarm that comes from the IDE and not from the standard console controller. The real problem:

 type Table takes type parameters def databaseCreate(tables: Table*) = { ^ one error found 

Then I followed the advice and changed the code:

 def databaseCreate(tables: Table[_]*)(implicit session: Session) = { for (table <- tables) { if (MTable.getTables(table.tableName).list.isEmpty) table.ddl.create } } 

Then I got this error:

 ambiguous implicit values: both value session of type slick.driver.MySQLDriver.simple.Session and method threadLocalSession in object Database of type => scala.slick.session.Session match expected type scala.slick.session.Session if (MTable.getTables(table.tableName).list.isEmpty) table.ddl.create ^ one error found 

My import is here:

 import play.api.GlobalSettings import play.api.Application import models.BlogData._ import scala.slick.driver.MySQLDriver.simple._ import Database.threadLocalSession import play.api.Play.current import scala.slick.jdbc.meta.MTable 
+3
scala playframework slick
source share
3 answers

Not sure why you are getting this error message. I will need to see your import and the place where you call databaseCreate , but what’s wrong: def databaseCreate(tables: Table*) should be def databaseCreate(tables: Table[_]*) and probably also take the second list of def databaseCreate(tables: Table[_]*)(implicit session: Session) = ... arguments def databaseCreate(tables: Table[_]*)(implicit session: Session) = ...

Alternatively, instead of table.getClass.getName, you can use table.tableName.

0
source share

In Slick 2: for the sake of completeness, see this and which are related to the flow.

I am using the following method:

 def createIfNotExists(tables: TableQuery[_ <: Table[_]]*)(implicit session: Session) { tables foreach {table => if(MTable.getTables(table.baseTableRow.tableName).list.isEmpty) table.ddl.create} } 

Then you can simply create your tables with an implicit session:

 db withSession { implicit session => createIfNotExists(table1, table2, ..., tablen) } 
+4
source share

You are using SLICK v1, I assume that you have Table objects. I have working code for v1. This version will delete any tables that are present before they are recreated (but do not delete any tables that you do not want to recreate). It will also merge DDL into one before creating to get the correct creation sequence:

 def create() = database withSession { import scala.slick.jdbc.{StaticQuery => Q} val tables = Seq(TableA, TableB, TableC) def existingTables = MTable.getTables.list().map(_.name.name) tables.filter(t => existingTables.contains(t.tableName)).foreach{t => Q.updateNA(s"drop table ${t.tableName} cascade").execute } val tablesToCreate = tables.filterNot(t => existingTables.contains(t.tableName)) val ddl: Option[DDL] = tablesToCreate.foldLeft(None: Option[DDL]){(ddl, table) => ddl match { case Some(d) => Some(d ++ table.ddl) case _ => Some(table.ddl) } } ddl.foreach{_.create} } 
+2
source share

All Articles