2015-10-11 32 views

回答

1

我對PostgresDriver做了一些解決方法,我創建了模塊,它將DDL打印到文件中。每次代碼更改後,我只需要更換1.SQL或稍後修改下一個演進的腳本:

ComputersDatabaseModule.scala

package bootstrap 

import com.google.inject.AbstractModule 
import play.api.{Mode, Play} 

class ComputersDatabaseModule extends AbstractModule { 

    protected def configure() = { 
    bind(classOf[CreateDDL]).asEagerSingleton() 
    bind(classOf[InitialData]).asEagerSingleton() 
    } 
} 

CreateDDL.scala

package bootstrap 

import java.io.PrintWriter 
import javax.inject.Inject 

import dao.{CompaniesMapping, ComputersMapping} 
import play.api.db.slick.{HasDatabaseConfigProvider, DatabaseConfigProvider} 
import slick.driver.JdbcProfile 


/** 
    * Creates DDL script 
    */ 
private[bootstrap] class CreateDDL @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) extends HasDatabaseConfigProvider[JdbcProfile] with 
    ComputersMapping with CompaniesMapping { 

    def createDDLScript() = { 
    import slick.driver.PostgresDriver.api._ 

    val allSchemas = companies.schema ++ computers.schema 

    val writer = new PrintWriter("target/migration_ddl.sql") 
    writer.write("# --- !Ups\n\n") 
    allSchemas.createStatements.foreach { s => writer.write(s + ";\n") } 

    writer.write("\n\n# --- !Downs\n\n") 
    allSchemas.dropStatements.foreach { s => writer.write(s + ";\n") } 

    writer.close() 
    } 

    createDDLScript() 
} 

ComputersDAO。斯卡拉

package dao 

import java.util.Date 
import javax.inject.{Inject, Singleton} 
import models.{Company, Computer, Page} 
import play.api.db.slick.{DatabaseConfigProvider, HasDatabaseConfigProvider} 
import play.api.libs.concurrent.Execution.Implicits.defaultContext 
import slick.driver.JdbcProfile 

import scala.concurrent.Future 

trait ComputersMapping { self: HasDatabaseConfigProvider[JdbcProfile] => 
    import driver.api._ 

    class Computers(tag: Tag) extends Table[Computer](tag, "COMPUTER") { 

    implicit val dateColumnType = MappedColumnType.base[Date, Long](d => d.getTime, d => new Date(d)) 

    def id = column[Long]("ID", O.PrimaryKey, O.AutoInc) 
    def name = column[String]("NAME") 
    def introduced = column[Option[Date]]("INTRODUCED") 
    def discontinued = column[Option[Date]]("DISCONTINUED") 
    def companyId = column[Option[Long]]("COMPANY_ID") 

    def * = (id.?, name, introduced, discontinued, companyId) <> (Computer.tupled, Computer.unapply) 
    } 

    val computers = TableQuery[Computers] 
} 

@Singleton() 
class ComputersDAO @Inject() (protected val dbConfigProvider: DatabaseConfigProvider) extends CompaniesMapping with ComputersMapping 
    with HasDatabaseConfigProvider[JdbcProfile] { 
    import driver.api._ 

    /** Retrieve a computer from the id. */ 
    def findById(id: Long): Future[Option[Computer]] = 
    db.run(computers.filter(_.id === id).result.headOption) 

    /** Count all computers. */ 
    def count(): Future[Int] = { 
    // this should be changed to 
    // db.run(computers.length.result) 
    // when https://github.com/slick/slick/issues/1237 is fixed 
    db.run(computers.map(_.id).length.result) 
    } 
    /** Count computers with a filter. */ 
    def count(filter: String): Future[Int] = { 
    db.run(computers.filter { computer => computer.name.toLowerCase like filter.toLowerCase }.length.result) 
    } 

    /** Return a page of (Computer,Company) */ 
    def list(page: Int = 0, pageSize: Int = 10, orderBy: Int = 1, filter: String = "%"): Future[Page[(Computer, Company)]] = { 

    val offset = pageSize * page 
    val query = 
     (for { 
     (computer, company) <- computers joinLeft companies on (_.companyId === _.id) 
     if computer.name.toLowerCase like filter.toLowerCase 
     } yield (computer, company.map(_.id), company.map(_.name))) 
     .drop(offset) 
     .take(pageSize) 

    for { 
     totalRows <- count(filter) 
     list = query.result.map { rows => rows.collect { case (computer, id, Some(name)) => (computer, Company(id, name)) } } 
     result <- db.run(list) 
    } yield Page(result, page, offset, totalRows) 
    } 

    /** Insert a new computer. */ 
    def insert(computer: Computer): Future[Unit] = 
    db.run(computers += computer).map(_ =>()) 

    /** Insert new computers. */ 
    def insert(computers: Seq[Computer]): Future[Unit] = 
    db.run(this.computers ++= computers).map(_ =>()) 

    /** Update a computer. */ 
    def update(id: Long, computer: Computer): Future[Unit] = { 
    val computerToUpdate: Computer = computer.copy(Some(id)) 
    db.run(computers.filter(_.id === id).update(computerToUpdate)).map(_ =>()) 
    } 

    /** Delete a computer. */ 
    def delete(id: Long): Future[Unit] = 
    db.run(computers.filter(_.id === id).delete).map(_ =>()) 

} 

添加的配置(application.config):

play.modules.enabled += "bootstrap.ComputersDatabaseModule" 
+0

我們是否有針對此問題在劇中框架項目​​問題跟蹤以下結果? –

0

隨着播放2.4和較新的,華而不實的插件沒有任何再創建變陣。爲此,我在開發模式中添加了一個頁面,該頁面始終顯示瀏覽器中所有演變的最新版本。這種方法與模塊系統即將發生的所有更改都兼容,因爲它不使用任何模塊。一個使用依賴注入,它使用您已在application.conf文件

我已經把下面的行配置配置正是油滑的數據庫驅動程序/路由

GET /evolutions.sql      controllers.SchemaEvolutionsController.evolutions 

然後創建一個控制器(應用程序/控制器/ SchemaEvolutionsController.scala

package controllers 

import com.google.inject.Inject 
import dao.CatDao 
import models.HasSchemaDescription 
import models.HasSchemaDescription.SqlSchemaDescription 
import play.api.Environment 
import play.api.mvc.{Action, Controller} 
import play.api.Mode 

class SchemaEvolutionsController @Inject() (environment: Environment, catDao : CatDao) extends Controller { 

    def allSchemas : Seq[HasSchemaDescription] = List(catDao) // List all schemas here 

    def descriptionsForAllSchemas : Seq[SqlSchemaDescription] = allSchemas.map(_.schemaDescription) 

    def evolutions = Action { 
    environment.mode match { 
     case Mode.Prod => NotFound 
     case _ => Ok(views.txt.evolutions(descriptionsForAllSchemas)).withHeaders(CONTENT_TYPE -> "text/plain") 
    } 
    } 
} 

對於此controlle ř當然還有一個對應的視圖(視圖/ evolutions.scala.txt

@import models.HasSchemaDescription.SqlSchemaDescription 
@(schemaDescriptions : Seq[SqlSchemaDescription]) 

# Get the newest version of this evolutions script on the address 
# http://localhost:[email protected](controllers.routes.SchemaEvolutionsController.evolutions) 
# when the server runs in development mode 


# --- !Ups 

@for(
    schemaDescription <- schemaDescriptions; 
    statement <- schemaDescription.createStatements) { 
@(statement.replaceAll(";",";;")); 
} 

# --- !Downs 

@for(
    schemaDescription <- schemaDescriptions; 
    statement <- schemaDescription.dropStatements) { 
@(statement.replaceAll(";",";;")); 
} 

對於我添加一個共同的特點,以獲得模式描述(應用/模型/ HasSchemaDescription)的DAO對象:

package models 

import models.HasSchemaDescription.SqlSchemaDescription 

trait HasSchemaDescription { 
    def schemaDescription: SqlSchemaDescription 
} 

object HasSchemaDescription { 
    type SqlSchemaDescription = slick.profile.SqlProfile#SchemaDescription 
} 

現在,每一個DAO對象,我必須實現的特點和DAO添加到SchemaEvolutionsController

例如,對於服務貓的DAO對象:

class CatDao @Inject()(protected val dbConfigProvider: DatabaseConfigProvider) 
    extends HasDatabaseConfigProvider[JdbcProfile] with HasSchemaDescription { 
    import driver.api._ 

    private val Cats = TableQuery[CatsTable] 

    def schemaDescription : SqlSchemaDescription = Cats.schema 

    def findById(id : Int) : Future[Option[Cat]] = db.run(Cats.filter(_.id === id).result.headOption) 

    private class CatsTable(tag: Tag) extends Table[Cat](tag, "CAT") { 

    def id = column[Int]("ID", O.PrimaryKey, O.AutoInc) 
    def name = column[String]("NAME") 
    def color = column[String]("COLOR") 
    def age = column[Option[Int]]("AGE") 

    def * = (id, name, color, age) <> (Cat.tupled, Cat.unapply _) 
    } 
} 

有了這個例子,你會得到http://localhost:9000/evolutions.sql

# Get the newest version of this evolutions script on the address 
# http://localhost:9000/evolutions.sql 
# when the server runs in development mode 


# --- !Ups 


create table `CAT` (`ID` INTEGER NOT NULL AUTO_INCREMENT PRIMARY KEY,`NAME` TEXT NOT NULL,`COLOR` TEXT NOT NULL,`AGE` INTEGER); 


# --- !Downs 


drop table `CAT`;