scala - Play 框架和自动生成的演变
问题描述
我喜欢用 Play 引导项目!Ebean,在内存数据库中:当我需要一个新模型时,进化会自动生成,这太棒了。
我正在学习 Play Scala,Ebean 和 Scala 之间缺乏支持
它可以工作,.enablePlugins(PlayScala, PlayEbean)
但不支持案例类作为 Ebean 模型。
我想知道,你知道一个 ORM 吗:
- 给定模型类自动生成 mysql 或 postgresql 模式
- 是 scala 友好的(尤其是案例类)
- 简约样板(这是一个 Ebean 模型,不需要像任何存储库那样的其他文件)
我不认为 slick 或 JPA 会产生进化?我试过了,但没有让它工作。
PS:使用案例类,您可以从/到 json 获得隐式读取器和写入器,这也很棒。
解决方案
我认为答案中提到的 Slick ORM 绝对是这里的方法。
Slick ORM 在 scala 中工作得很好,因为您可以在这个特定的 ORM 中使用诸如filter
,map
和其他功能范式的操作。另一方面,slick 有很棒的文档,你可以从这个链接中看到:
http://slick.lightbend.com/doc/3.1.0/
假设您对 ORM 开放,我们可以轻松地继续使用slick-codegen
库,该库会自动反映您的数据库模式并创建一个包含数据库中所有模型的文件。
该文档专门在这里slick-codegen
:
http ://slick.lightbend.com/doc/3.1.0/code-generation.html
但我会为你分解它,让它变得更容易。执行此操作的方法如下postgres
:
- 通过在 build.sbt 中添加这一行来添加
slick-codegen
到您的库依赖项:libraryDependencies += "com.typesafe.slick" %% "slick-codegen" % "3.1.0"
- 确保您的数据库在 postgres 的任何端口(比如说 5432)上运行,并
postgresql
在 build.sbt 中包含适当的驱动程序 在您的项目中创建以下 scala 文件(您可以右键单击以在 IntelliJ 中运行,或者如果您不使用 IntelliJ,则可能必须将其更改为可执行的 Scala 文件。人们还想出了一种通过 sbt 本身运行它的方法在编译期间,但我不会进入):
object SlickCodeGen { def main(args: Array[String]): Unit = { slick.codegen.SourceCodeGenerator.main( Array("slick.jdbc.PostgresProfile", "org.postgresql.Driver", DATABASE_URL, DIRECTORY_TO_PLACE_FILE, PACKAGE, USERNAME, PASSWORD) ) } }
运行 scala 文件后,您将看到
Tables.scala
在您之前指定的目录和包中调用的新文件。该文件包含最少且唯一必要的组件,例如,对于
Computer
您在链接中显示的表格,将生成从数据库到案例类的隐式转换,可能如下所示(仅用于演示目的,但如果样板文件太多,文件的长度将大致相同):package // AUTO-GENERATED Slick data model /** Stand-alone Slick data model for immediate use */ object Tables extends { val profile = slick.jdbc.PostgresProfile } with Tables /** Slick data model trait for extension, choice of backend or usage in the cake pattern. (Make sure to initialize this late.) */ trait Tables { val profile: slick.jdbc.JdbcProfile import profile.api._ import slick.model.ForeignKeyAction // NOTE: GetResult mappers for plain SQL are only generated for tables where Slick knows how to map the types of all columns. import slick.jdbc.{GetResult => GR} /** DDL for all tables. Call .create to execute. */ lazy val schema : profile.SchemaDescription = Computer.schema @deprecated("Use .schema instead of .ddl", "3.0") def ddl = schema case class ComputerRow(name: String, introduced: Date, discontinued: Date, company: Company) /** GetResult implicit for fetching ComputerRow objects using plain SQL queries */ implicit def GetResultComputerRow(implicit e0: GR[String], e1: GR[Date], e2: GR[Company]): GR[ComputerRow] = GR { prs => import prs._ ComputerRow.tupled( (<<[String], <<[Date], <<[Date], <<[Company])) } /** Table description of table computer. Objects of this class serve as prototypes for rows in queries. */ class Computers(_tableTag: Tag) extends profile.api.Table[ComputerRow](_tableTag, None, "computer") { def * = (name, introduced, discontinued, company) <> (ComputerRow.tupled, ComputerRow.unapply) /** Maps whole row to an option. Useful for outer joins. */ def ? = (Rep.Some(name), Rep.Some(introduced), Rep.Some(discontinued), Rep.Some(company).shaped.<>( { r => import r._; _1.map( _ => ComputerRow.tupled( (_1.get, _2.get, _3.get, _4.get))) }, (_: Any) => throw new Exception("Inserting into ? projection not supported.") ) /** Database column name SqlType(text) */ val name: Rep[String] = column[String]("name", O.PrimaryKey) /** Database column introduced SqlType(date) */ val firstName: Rep[Date] = column[Date]("introduced") /** Database column discontinued SqlType(date) */ val lastName: Rep[Date] = column[Date]("discontinued") /** Database column company SqlType(text) */ val gender: Rep[Company] = column[Company]("company") } /** Collection-like TableQuery object for table Computer */ lazy val Computer = new TableQuery(tag => new Computer(tag)) }
- 创建此文件后,您可以轻松地利用案例类(如您所愿),一个示例是当您需要向计算机表添加新行时,您可以简单地执行
Computer += ComputerRow(...)
- 创建此文件后,您可以轻松地利用案例类(如您所愿),一个示例是当您需要向计算机表添加新行时,您可以简单地执行
请注意,此处的 ComputerRow 是一个案例类。
所以总结一下,
slick-codegen
可以从数据库自动生成你的 scala 类,或者Computer.schema
在这种情况下运行相反的方式。slick
对 scala 非常友好(案例类,monad 操作)- 不错的样板,但真正用于您的应用程序,也可以自定义,所有表可以在一个文件中创建或根据您的需要分开。
我认为这里的 Slick 不会出错。
推荐阅读
- system-verilog - Systemverilog 扩展规则
- javascript - 更新到 discord.js v13 时出现 keyArray 问题
- android - 是否可以在 AAR 中包含一些 maven url?
- ruby-on-rails - 默认情况下不加载固定装置
- docker - 无法从 Docker 容器外部访问我的应用程序,但在容器内一切正常
- r - 为什么在albersusa中的points_elided会给出奇怪的结果?
- authentication - App\Http\Controllers\Auth\RegisterController::create():参数 #1 ($request) 必须是 App\Http\Requests\RegisterRequest 类型,给定数组
- azure - 由于附加了“api://”,Azure AD 受众无效
- php - MySQL 插入查询在 Localhost MySQL 数据库上工作,但不在在线 MySQL 数据库上
- excel - 当查找值具有需要分组到同一类别中的变化时如何查找