Oui, c'est possible.
Créer un nouveau fichier dans ce chemin: your/modules/folder/EvolutionsModule.scala
Ensuite, ajoutez ce qui suit:
package your.modules.folder
import javax.inject._
import play.api.db.evolutions._
import play.api.inject.{ Module }
import play.api.libs.Collections
import play.api.{ Configuration, Environment }
import org.apache.commons.io.FileUtils
class EvolutionsModule extends Module {
def bindings(environment: Environment, configuration: Configuration) = {
Seq(
bind[EvolutionsConfig].toProvider[DefaultEvolutionsConfigParser],
bind[EvolutionsReader].to[YourEvolutionsReader],
bind[EvolutionsApi].to[DefaultEvolutionsApi],
bind[ApplicationEvolutions].toProvider[ApplicationEvolutionsProvider].eagerly
)
}
}
@Singleton
class YourEvolutionsReader @Inject()(environment: Environment) extends EvolutionsReader {
def evolutions(db: String): Seq[Evolution] = {
val upsMarker = """^#.*!Ups.*$""".r
val downsMarker = """^#.*!Downs.*$""".r
val UPS = "UPS"
val DOWNS = "DOWNS"
val UNKNOWN = "UNKNOWN"
val mapUpsAndDowns: PartialFunction[String, String] = {
case upsMarker() => UPS
case downsMarker() => DOWNS
case _ => UNKNOWN
}
val isMarker: PartialFunction[String, Boolean] = {
case upsMarker() => true
case downsMarker() => true
case _ => false
}
val folder = environment.getFile(Evolutions.directoryName(db))
val sqlFiles = folder.listFiles()
.filter(file => file.getName.indexOf(".sql") > -1)
.sortBy(file => {
val fileName = file.getName
val nameAfterSqlNumber = fileName.split("\\.")(0).split("_").drop(1).mkString("") + ".sql"
val sqlNumber = fileName.split("\\.")(0).split("_")(0).toInt
val newPrefix = "%07d".format(sqlNumber)
newPrefix + nameAfterSqlNumber
})
.toSeq
sqlFiles.zip(1 to sqlFiles.size)
.map {
case (file, revision) => {
val script = FileUtils.readFileToString(file)
val parsed = Collections.unfoldLeft(("", script.split('\n').toList.map(_.trim))) {
case (_, Nil) => None
case (context, lines) => {
val (some, next) = lines.span(l => !isMarker(l))
Some((next.headOption.map(c => (mapUpsAndDowns(c), next.tail)).getOrElse("" -> Nil),
context -> some.mkString("\n")))
}
}.reverse.drop(1).groupBy(i => i._1).mapValues { _.map(_._2).mkString("\n").trim }
Evolution(
revision,
parsed.getOrElse(UPS, ""),
parsed.getOrElse(DOWNS, "")
)
}
}
}
}
Accédez à votre applications.conf
, puis ajouter ces lignes. Ceci est pour remplacer le EvolutionsModule
par défaut avec notre très propre.
play.modules {
enabled += "your.modules.folder.EvolutionsModule"
disabled += "play.api.db.evolutions.EvolutionsModule"
}
Explication pour le premier bloc de texte:
- Selon le code source, les évolutions sont ajoutés uniquement basée sur une seule classe et de méthode - la
EvolutionsReader
et la méthode evolutions
.
- Après l'exécution de la méthode
evolutions
, le module d'évolutions s'appuiera sur les entrées de la base de données générées. Donc, nous avons seulement besoin de remplacer cette méthode par la nôtre.
- Malgré l'énorme bloc de code, il s'agit en fait d'une modification mineure du code source. J'ai remplacé la fonctionnalité de la fonction
loadResource
par la liste des fichiers dans le dossier evolutions sql files. Le reste est une copie straight-up de la méthode evolutions
dans EvolutionsApi.scala
Les codes sources citées by this answer sont des fonctions utilitaires les plus probables - le module Evolutions ne repose pas vraiment sur elle. Je n'ai pas trouvé d'utilisation significative de fileName
et resourceName
pour exécuter le evolutions
. Au lieu de cela, ils référencent tous le tableau play_evolutions
.
Référence: https://github.com/playframework/playframework/issues/6919
Wow, merci ... mais nous sommes passés à https://flywaydb.org déjà. – Sergey
@Sergey Tout va bien. IMO, abandonner complètement les évolutions et changer de décision est la bonne décision (et laisser tomber, mais c'est une autre histoire). mais je ne pouvais pas parce que je hérite d'un projet. Pourtant, je voulais que cette question ait la bonne réponse pour référence future pour moi et les autres mainteneurs de code, et surtout parce que j'utiliserai Scala pendant très, très longtemps. – blindbox