- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用Slick与 Play Framework 2.1,我遇到了一些麻烦。
给定以下实体...
package models
import scala.slick.driver.PostgresDriver.simple._
case class Account(id: Option[Long], email: String, password: String)
object Accounts extends Table[Account]("account") {
def id = column[Long]("id", O.PrimaryKey, O.AutoInc)
def email = column[String]("email")
def password = column[String]("password")
def * = id.? ~ email ~ password <> (Account, Account.unapply _)
}
...我必须为特定数据库驱动程序导入包,但我想使用H2进行测试和生产中的 PostgreSQL。我应该如何进行?
我能够通过覆盖单元测试中的驱动程序设置来解决此问题:
package test
import org.specs2.mutable._
import play.api.test._
import play.api.test.Helpers._
import scala.slick.driver.H2Driver.simple._
import Database.threadLocalSession
import models.{Accounts, Account}
class AccountSpec extends Specification {
"An Account" should {
"be creatable" in {
Database.forURL("jdbc:h2:mem:test1", driver = "org.h2.Driver") withSession {
Accounts.ddl.create
Accounts.insert(Account(None, "user@gmail.com", "Password"))
val account = for (account <- Accounts) yield account
account.first.id.get mustEqual 1
}
}
}
}
我不喜欢这个解决方案,我想知道是否有一种优雅的方法来编写与数据库无关的代码,以便使用两种不同的数据库引擎 - 一个用于测试,另一个用于生产?
我也不想使用进化,更喜欢让 Slick 为我创建数据库表:
import play.api.Application
import play.api.GlobalSettings
import play.api.Play.current
import play.api.db.DB
import scala.slick.driver.PostgresDriver.simple._
import Database.threadLocalSession
import models.Accounts
object Global extends GlobalSettings {
override def onStart(app: Application) {
lazy val database = Database.forDataSource(DB.getDataSource())
database withSession {
Accounts.ddl.create
}
}
}
第一次启动应用程序时,一切正常...然后,当然,第二次启动应用程序时,它崩溃了,因为表已经存在于 PostgreSQL 数据库中。
也就是说,我的最后两个问题是:
onStart
方法与数据库无关,以便我可以使用 FakeApplication
测试我的应用程序?最佳答案
您可以在此处找到有关如何使用蛋糕模式/依赖项注入(inject)将 Slick 驱动程序与数据库访问层解耦的示例:https://github.com/slick/slick-examples .
前几天我为play写了一个Slick集成库,将驱动依赖移到了Play项目的application.conf中:https://github.com/danieldietrich/slick-integration .
借助该库,您的示例将实现如下:
1) 添加依赖到project/Build.scala
"net.danieldietrich" %% "slick-integration" % "1.0-SNAPSHOT"
添加快照存储库
resolvers += "Daniel's Repository" at "http://danieldietrich.net/repository/snapshots"
或者本地存储库,如果 slick-integration 是在本地发布的
resolvers += Resolver.mavenLocal
2) 将 Slick 驱动程序添加到 conf/application.conf
slick.default.driver=scala.slick.driver.H2Driver
3) 实现 app/models/Account.scala
在 slick-integration 的情况下,假设您使用自动递增的 Long 类型的主键。 pk 名称是“id”。 Table/Mapper 实现具有默认方法(delete、findAll、findById、insert、update)。您的实体必须实现“插入”方法所需的“withId”。
package models
import scala.slick.integration._
case class Account(id: Option[Long], email: String, password: String)
extends Entity[Account] {
// currently needed by Mapper.create to set the auto generated id
def withId(id: Long): Account = copy(id = Some(id))
}
// use cake pattern to 'inject' the Slick driver
trait AccountComponent extends _Component { self: Profile =>
import profile.simple._
object Accounts extends Mapper[Account]("account") {
// def id is defined in Mapper
def email = column[String]("email")
def password = column[String]("password")
def * = id.? ~ email ~ password <> (Account, Account.unapply _)
}
}
4) 实现 app/models/DAL.scala
这是数据访问层(DAL), Controller 使用它来访问数据库。事务由相应组件内的表/映射器实现处理。
package models
import scala.slick.integration.PlayProfile
import scala.slick.integration._DAL
import scala.slick.lifted.DDL
import play.api.Play.current
class DAL(dbName: String) extends _DAL with AccountComponent
/* with FooBarBazComponent */ with PlayProfile {
// trait Profile implementation
val profile = loadProfile(dbName)
def db = dbProvider(dbName)
// _DAL.ddl implementation
lazy val ddl: DDL = Accounts.ddl // ++ FooBarBazs.ddl
}
object DAL extends DAL("default")
5) 实现 test/test/AccountSpec.scala
package test
import models._
import models.DAL._
import org.specs2.mutable.Specification
import play.api.test.FakeApplication
import play.api.test.Helpers._
import scala.slick.session.Session
class AccountSpec extends Specification {
def fakeApp[T](block: => T): T =
running(FakeApplication(additionalConfiguration = inMemoryDatabase() ++
Map("slick.default.driver" -> "scala.slick.driver.H2Driver",
"evolutionplugin" -> "disabled"))) {
try {
db.withSession { implicit s: Session =>
try {
create
block
} finally {
drop
}
}
}
}
"An Account" should {
"be creatable" in fakeApp {
val account = Accounts.insert(Account(None, "user@gmail.com", "Password"))
val id = account.id
id mustNotEqual None
Accounts.findById(id.get) mustEqual Some(account)
}
}
}
我无法给你这个问题的充分答案...
...但这也许并不是您真正想做的事情。如果您向表添加一个属性(例如 Account.active
)会怎样?如果您想保护当前存储在表中的数据,那么更改脚本就可以完成这项工作。目前,这样的更改脚本必须手动编写。 DAL.ddl.createStatements 可用于检索创建语句。应该对它们进行排序,以便更好地与以前的版本进行比较。然后使用 diff(与以前的版本)来手动创建更改脚本。在这里,演化用于改变数据库模式。
这是一个关于如何生成(第一个)进化的示例:
object EvolutionGenerator extends App {
import models.DAL
import play.api.test._
import play.api.test.Helpers._
running(FakeApplication(additionalConfiguration = inMemoryDatabase() ++
Map("slick.default.driver" -> "scala.slick.driver.PostgresDriver",
"evolutionplugin" -> "disabled"))) {
val evolution = (
"""|# --- !Ups
|""" + DAL.ddl.createStatements.mkString("\n", ";\n\n", ";\n") +
"""|
|# --- !Downs
|""" + DAL.ddl.dropStatements.mkString("\n", ";\n\n", ";\n")).stripMargin
println(evolution)
}
}
关于scala - 如何编写与数据库无关的 Play 应用程序并执行首次数据库初始化?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13661339/
假设我们要描述一个满足以下真值表的组合电路: a b | s0 s1 s2 s3 ----------------- 0 0 | 1 d d d 0 1 | 0 1 d d 1 0 |
.mainIDv { height:300px; width:400px; padding:5px; margin: 8px auto 8px auto; } .ImgDisp{
我的 iOS 应用程序遇到了一个恼人的问题。突然,当我启动带有 TableView 的 View Controller 时,出现以下错误: Unrecognized selector sent to
我有一个简单的 PreferenceActivity 类,它的 onCreate 将我的 R.xml.preferences 屏幕传递给 ((PreferenceActivity)super).add
在大学项目范围内,我应该实现数据库的聚合。 我得到了一个实体关系模型,它看起来与此类似: 现在我应该实现一个 SQL 脚本来创建这样的数据库,但我在谷歌或其他任何地方找不到有关此主题的任何内容。在我教
我一直在努力阅读 GCD 并试图弄明白。我读了很多地方,应该始终使用 GCD,如果一个人正在做一些繁重的工作,这会卡住 UI,我确实理解这一点,但是 GCD 也可以仅仅为了性能而使用吗?假设我有一个循
当有人用他们自己的类重载线程时,这个问题似乎已经以一种或另一种形式得到了回答,但是如果只是尝试使用 QTimer 类而不扩展 QThread 类呢?我正在尝试将 QTimer 用于 QT。他们在 上的
在网上看了类似的问题/错误,没有一个对我有帮助... 未处理的拒绝 SequelizeEagerLoadingError:任务未关联到用户! 我的用户路线 router.get('', functio
如果我正在评估两个变量而不是两个方法调用,那么我使用“&&”或“&”是否重要 //some logic that sets bool values boolean X = true; boolean
我们目前正在内部为我们的项目使用 Oracle 10g,这不太可能改变,但最终我们将向其他客户提供此应用程序,我们需要能够提出替代的免费数据库。 那么使 Hibernate 持久层独立于所使用的底层
我的 AsyncTask 类中的 onPostExecute() 方法有问题。 我有一个SignupActivity: public class SignupActivity extends AppC
已结束。此问题正在寻求书籍、工具、软件库等的推荐。它不满足Stack Overflow guidelines 。目前不接受答案。 我们不允许提出寻求书籍、工具、软件库等推荐的问题。您可以编辑问题,以便
我一直在大量关注 sequelize 的文档,但在处理关系时遇到了问题。这是我使用 belongsTo 创建两个非常基本的 1:1 关系的非常简单的代码 import Sequelize, { STR
我希望这与 GMT 无关,否则我会觉得自己很愚蠢。 2 个快速相关的问题。为什么这会转换为不同的日期?正在失去一天。我查看了其他答案中所述的时区,但它始终是 GMT 时区 0000,这正是我所期望的。
我发现了这个问题的很多版本,但似乎都没有比明显的 Google Chrome 错误更进一步。 发生的情况是,每当我将 codeigniter 设置复制到服务器上的新文件夹,以基于它启动新项目时,我在尝
我需要一个与 UI 无关的简单布局管理器。通过这个,我的意思是它不应该指定我想如何在屏幕上表示我的形状/控件。它应该能让我说: 我想要 X 形状。我想要 X 形下的 Y 形。我希望形状 Z 包围 X,
当有一个方法== , 方法 !=被定义为采用该结果并应用 !给它。 (可能还有 =~ 和 !~ 。) 与此不同,>= , 通常表示 >或 == , 实际上独立于 >和 == .这两个定义似乎都不会影响
我在 Ruby Netbeans 6.5.1 中获得了大量(我称之为)无关的自动完成信息。 例如,如果我输入一个模型对象的名称,然后输入一个句点(无论我是在 Controller 中还是在 View
我是 NodeJS 的新手,有 express 和 Sequelize。当我想创建图书租赁时,控制台会提示我“图书与租赁无关”。 当我将表迁移到 sql 数据库时,id 就在它们的位置并且我的播种机正
我有众所周知的错误: implicit declaration of function 'STLINKReadSytemCalls' [-Wimplicit-function-declaration]
我是一名优秀的程序员,十分优秀!