Test of automatic schema update.

This commit is contained in:
takezoe
2013-04-26 11:17:57 +09:00
parent 4e9bcb0d2f
commit ffd74394b4
4 changed files with 114 additions and 66 deletions

View File

@@ -0,0 +1,11 @@
-- Test Script for Database Migration
CREATE TABLE ACCOUNT (
USER_ID INT PRIMARY KEY,
USER_NAME VARCHAR(100) NOT NULL
);
CREATE TABLE PROJECT (
PROJECT_ID INT PRIMARY KEY,
PROJECT_NAME VARCHAR(100) NOT NULL
);

View File

@@ -0,0 +1,102 @@
package util
import java.io.File
import java.sql.Connection
import org.apache.commons.io.FileUtils
import javax.servlet.ServletContextEvent
import org.apache.commons.io.IOUtils
import org.slf4j.Logger
import org.slf4j.LoggerFactory
object AutoUpdate {
case class Version(majorVersion: Int, minorVersion: Int){
val logger = LoggerFactory.getLogger(classOf[Version])
def update(conn: Connection): Unit = {
val sqlPath = "update/%d.%d.sq".format(majorVersion, minorVersion)
val in = Thread.currentThread.getContextClassLoader.getResourceAsStream(sqlPath)
if(in != null){
val sql = IOUtils.toString(in)
val stmt = conn.createStatement()
try {
logger.debug(sqlPath + "=" + sql)
stmt.executeUpdate(sql)
} finally {
stmt.close()
}
}
}
val versionString = "%d.%d".format(majorVersion, minorVersion)
}
/**
* The history of versions. A head of this sequence is the current BitBucket version.
*/
val versions = Seq(
Version(1, 0)
)
/**
* The head version of BitBucket.
*/
val headVersion = versions.head
/**
* The version file (GITBUCKET_HOME/version).
*/
val versionFile = new File(Directory.GitBucketHome, "version")
/**
* Returns the current version from the version file.
*/
def getCurrentVersion(): Version = {
if(versionFile.exists){
FileUtils.readFileToString(versionFile).split(".") match {
case Array(majorVersion, minorVersion) => {
versions.find { v => v.majorVersion == majorVersion.toInt && v.minorVersion == minorVersion.toInt }.get
}
case _ => Version(0, 0)
}
} else {
Version(0, 0)
}
}
}
/**
* Start H2 database and update schema automatically.
*/
class AutoUpdateListener extends org.h2.server.web.DbStarter {
import AutoUpdate._
val logger = LoggerFactory.getLogger(classOf[AutoUpdateListener])
override def contextInitialized(event: ServletContextEvent): Unit = {
super.contextInitialized(event)
logger.debug("H2 started")
logger.debug("Start migration")
val conn = getConnection()
try {
val currentVersion = getCurrentVersion()
versions.takeWhile(_ != currentVersion).reverse.foreach(_.update(conn))
FileUtils.writeStringToFile(versionFile, headVersion.majorVersion + "." + headVersion.minorVersion)
logger.debug("Migrate from " + currentVersion.versionString + " to " + headVersion.versionString)
conn.commit()
} catch {
case ex: Throwable => {
logger.error("Failed to migrate", ex)
conn.rollback()
}
}
logger.debug("End migration")
}
}

View File

@@ -1,65 +0,0 @@
package util
import java.io._
import org.apache.commons.io.FileUtils
object Migration {
/**
* Define Migrator interface.
*/
trait Migrator {
def migrate(): Unit
}
/**
* Migrate H2 database by SQL files.
*/
case class DatabaseMigrator(sqlPath: String) extends Migrator {
def migrate(): Unit = {
// TODO
}
}
case class Version(majorVersion: Int, minorVersion: Int, migrators: Migrator*)
/**
* The history of versions. A head of this sequence is the current BitBucket version.
* Migration#migrate() updates the data directory to move to the head version.
*/
val versions = Seq(
Version(1, 0, DatabaseMigrator("migration/1.0/createdb.sql"))
)
/**
* The head version of BitBucket.
*/
val headVersion = versions.head
/**
* The version file (GITBUCKET_HOME/version).
*/
val versionFile = new File(Directory.GitBucketHome, "version")
/**
* Returns the current version
*/
def getCurrentVersion(): Version = {
FileUtils.readFileToString(versionFile).split(".") match {
case Array(majorVersion, minorVersion) => {
versions.find { v => v.majorVersion == majorVersion.toInt && v.minorVersion == minorVersion.toInt }.get
}
}
}
/**
* Do migrate old data directory to the head version.
*/
def migrate(): Unit = {
val currentVersion = getCurrentVersion()
versions.takeWhile(_ != currentVersion).reverse.foreach(_.migrators.foreach(_.migrate()))
FileUtils.writeStringToFile(versionFile, headVersion.majorVersion + "." + headVersion.minorVersion)
}
}

View File

@@ -35,7 +35,7 @@
<!-- H2 database configuration --> <!-- H2 database configuration -->
<!-- ===================================================================== --> <!-- ===================================================================== -->
<listener> <listener>
<listener-class>org.h2.server.web.DbStarter</listener-class> <listener-class>util.AutoUpdateListener</listener-class>
</listener> </listener>
<context-param> <context-param>