Play框架的进化文件兼容Postgres和H2两种数据库。

4
我一直在使用Play框架(scala)和H2作为后端开发网站。测试很好集成,特别是能够对内存中的H2数据库运行测试。
现在我想将我的数据存储迁移到Postgres上,出于各种方便的原因。这给我留下了一个问题:如何继续测试并保留每个测试运行的新鲜数据库的简单性?我在网上看到一些人通过在Postgres上实时运行并在H2上进行测试来解决这个问题。然而,在SQL层面上两者并不完全兼容(即使是在Postgres兼容模式下的H2)。例如,SERIAL、BIGSERIAL和BYTEA在H2上不受支持。
我可以通过使用两种方言的约束兼容交集来解决这个问题,还是我错过了其他技术?
感谢任何帮助。
Alex
2个回答

2

我知道这是一个较旧的帖子,但看起来多年后仍然没有明显的解决方案。作为一种短期解决方法,在play 2.4.x-2.5.x(到目前为止只在那里进行了测试)中,您可以通过创建自定义进化读取器来改变测试期间应用进化的方式:

package support

import play.api.db.evolutions.{ClassLoaderEvolutionsReader, Evolutions, ResourceEvolutionsReader}

import java.io.{ByteArrayInputStream, InputStream}
import java.nio.charset.StandardCharsets
import scala.io.Source
import scala.util.Try

class EvolutionTransformingReader(
    classLoader: ClassLoader = classOf[ClassLoaderEvolutionsReader].getClassLoader,
    prefix: String = "")
  extends ResourceEvolutionsReader {

  def loadResource(db: String, revision: Int): Option[InputStream] =
    for {
      stream <- Option(classLoader.getResourceAsStream(prefix + Evolutions.resourceName(db, revision)))
      lines <- Try(Source.fromInputStream(stream).getLines).toOption
      updated = lines map convertPostgresLinesToH2
    } yield convertLinesToInputStream(updated)

  private val ColumnRename = """(?i)\s*ALTER TABLE (\w+) RENAME COLUMN (\w+) TO (\w+);""".r

  private def convertPostgresLinesToH2(line: String): String =
    line match {
      case ColumnRename(tableName, oldColumn, newColumn) =>
        s"""ALTER TABLE $tableName ALTER COLUMN $oldColumn RENAME TO $newColumn;"""
      case _ => line
    }

  private def convertLinesToInputStream(lines: Iterator[String]): InputStream =
    new ByteArrayInputStream(lines.mkString("\n").getBytes(StandardCharsets.UTF_8))
}

然后将其传递到应用进化期间进行测试的位置:

Evolutions.applyEvolutions(registry.database, new EvolutionTransformingReader())

请注意,读者仍处于相当愚笨的状态(它假设 SQL 语句都是单行语句,这并不保证),但这足以让任何人开始学习。

很高兴知道至少有一种方法可以解决这个问题。我们仍然在使用Play 2.3,似乎没有办法只是重命名列名。这就是为什么标准很重要,只有所有供应商都遵循它... - Nader Ghanbari
在最新版本中,ALTER TABLE ... RENAME COLUMN ... TO ... 的更改不再需要。但是不要忘记(在PostgreSQL中可选的)COLUMN,在H2中它是必需的。 - Itchy

1

由于进化文件直接使用 SQL,除非您将自己限制在通用的跨数据库兼容子集上,否则可能会出现问题。

这方面没有真正的解决方案,但您仍然可以使用一个新的数据库进行测试。只需设置以下内容:

%test.jpa.ddl=create-drop
%test.db.driver=org.postgresql.Driver
%test.db=<jdbc url>
//etc

这应该为测试创建一个新的Postgres连接,从头开始创建数据库,运行演化,进行测试并在完成后删除所有数据。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接