Play Framework и автоматически генерируемые эволюции - PullRequest
0 голосов
/ 22 ноября 2018

Я люблю загрузочные проекты с Play!Ebean, в базе данных памяти: evolutions генерируется автоматически, когда мне нужна новая модель, это потрясающе.

Я изучаю Play Scala, и между Ebean и Scala отсутствует поддержка

Itможет работать с .enablePlugins(PlayScala, PlayEbean) Но классы case не поддерживаются в качестве модели Ebean.

Мне было интересно, знаете ли вы ORM, который:

  • автоматически генерирует заданную схему mysql или postgresqlклассы моделей
  • дружественны к scala (особенно с классами кейсов)
  • минималистичный шаблон ( this - это модель Ebean без необходимости использования другого файла, такого как любой репозиторий)

Я не думаю, что пятно или JPA порождают эволюцию?Я пытался, но у меня не получилось.

PS: с классами case вы получаете неявных читателей и писателей из / в json, и это тоже потрясающе.

1 Ответ

0 голосов
/ 29 ноября 2018

Я думаю, что 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:

  1. Добавьте slick-codegen в зависимости вашей библиотеки, добавив эту строку в свой build.sbt: libraryDependencies += "com.typesafe.slick" %% "slick-codegen" % "3.1.0"
  2. Makeубедитесь, что ваша база данных работает на любом порту (скажем, 5432) для postgres и включите соответствующий драйвер postgresql в ваш build.sbt
  3. Создайте следующий файл 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) ) } }

  4. После запуска файла scala вы увидите новый файл с именем Tables.scala в каталоге и пакете, которые вы ранее

  5. Файл содержит минимальные и только необходимые вам компоненты, например, для такой таблицы, как 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))
    }
    
  6. После создания этого файла вы можете легко использовать классы дел (как вы и хотели), например, когда вам нужно добавить новую строку в таблицу компьютеров, вы можете просто сделать Computer += ComputerRow(...)

Обратите внимание, что ComputerRow здесь является классом дела.

Итак, чтобы подвести итог,

  1. slick-codegen может сгенерировать вашу scalaклассы автоматически из базы данных, или наоборот, с помощью Computer.schema в этом случае.
  2. slick чрезвычайно удобен для scala (тематические классы, операции с монадой)
  3. достойный пример, но на самом делеиспользовать для использования в вашем приложении, также могут быть настроены, и все таблицы могут быть созданы в одном файле или разделены в зависимости от ваших потребностей.

Я думаю, вы не ошибетесь с Сликом здесь.

...