Я думаю, что Slick ORM, как упомянуто в ответах, определенно является подходящим вариантом.
Slick ORM отлично работает в scala, поскольку вы можете использовать такие операции, как filter
, map
и другие функциональные парадигмы в данном конкретном ORM.С другой стороны, у 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
:
- Добавьте
slick-codegen
в зависимости вашей библиотеки, добавив эту строку в свой build.sbt: libraryDependencies += "com.typesafe.slick" %% "slick-codegen" % "3.1.0"
- Makeубедитесь, что ваша база данных работает на любом порту (скажем, 5432) для postgres и включите соответствующий драйвер
postgresql
в ваш build.sbt Создайте следующий файл scala в своем проекте (который вы можете исправитьщелкните для запуска в IntelliJ или, возможно, придется изменить его на исполняемый файл Scala, если вы не используете IntelliJ. Люди также нашли способ запустить это через сам 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
, которую вы указали в своей ссылке, неявные преобразования избаза данных дляклассы case будут сгенерированы и могут выглядеть следующим образом (только для демонстрационных целей, но длина файла будет примерно такой же, если это слишком много в шаблоне):
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 (тематические классы, операции с монадой) - достойный пример, но на самом делеиспользовать для использования в вашем приложении, также могут быть настроены, и все таблицы могут быть созданы в одном файле или разделены в зависимости от ваших потребностей.
Я думаю, вы не ошибетесь с Сликом здесь.