取得領先
VMware 提供培訓和認證,以加速您的進展。
了解更多Grails 的許多優點之一是它可以自動從您的網域模型建立資料庫綱要。 誠然,這是 Grails 使用的 Hibernate 的一項功能,但它仍然可以幫助您快速開始使用資料庫驅動的 Web 應用程式,而無需擔心資料庫綱要。
您的應用程式進入生產環境後會發生什麼事? 在開發過程中,伺服器運行之間遺失資料並不是一個大問題。 但是您不能只是在生產環境中刪除資料庫。 因此,排除了dbCreate資料來源設定的 "create" 和 "create-drop" 值。 "update" 呢? 它不會清除您資料庫中的資料,所以經常被人們使用。 然而,它在生產環境中並不好用,因為它有很大的限制。 例如,它無法處理簡單的欄位重新命名,當然也無法處理對現有資料的修改,而這些修改可能是升級的必要部分。 雖然很想使用dbCreate = "update"進行部署到生產環境,但它通常是錯誤的解決方案。
那剩下什麼給你? 用於執行遷移的 SQL 腳本? 這當然有可能,但為 GORM 網域模型中的特定變更建立適當的 SQL 並不容易。 如果您需要支援多種資料庫類型,這也不合適,因為 SQL 可能因每種資料庫而異。
幸運的是,有一個靈活且與資料庫無關的工具可用於執行綱要遷移:Liquibase。 更好的是,有兩個 Grails 插件讓使用 Liquibase 比原本的情況更容易:Liquibase 插件 和 Autobase。
因此,如果這些插件已經存在很長時間了,那麼 Grails 2.0 的新功能是什麼? 資料庫遷移是使用 Grails 進行任何嚴肅工作的重要部分,因此 Grails 團隊決定應該有一種官方方式來處理它們。 結果是一個新的插件,它結合了 Liquibase 和 Autobase 插件的最佳部分:資料庫遷移插件。
即使核心資料庫遷移支援是 Grails 2.0 路線圖的一部分,也沒有理由將其與該版本綁定。 這意味著您也可以在 Grails 1.3 專案中使用該插件。 該插件為您的應用程式帶來了以下功能
它提供了超過 20 個命令,讓您擁有充分的控制權。 您可以從插件的 使用者指南 中找到更多資訊,但簡而言之,它為管理 Grails 應用程式新版本的受控資料庫升級提供了很大的幫助。 如果您願意,仍然可以使用其他插件,甚至完全不同的方法,但對於大多數使用者來說,這絕對是最佳選擇。
本文的其餘部分將向您展示該插件的常見使用模式。
假設您一直在努力開發一個 Grails 應用程式,現在您想要將第一個版本部署到生產環境。 現在是考慮如何管理資料庫升級的時候了。 此時,生產資料庫甚至尚未建立。 因此,將資料庫遷移插件宣告為 runtime 依賴項,如下所示
grails.project.dependency.resolution = {
inherits "global"
...
plugins {
runtime ":database-migration:1.0"
compile ":hibernate:$grailsVersion"
compile ":jquery:1.6.1.1"
compile ":resources:1.0.2"
build ":tomcat:$grailsVersion"
}
...
}
並執行grails compile。 在撰寫本文時,1.0 是該插件的最新版本。 請查看 Grails 插件入口網站,以了解任何指定時間的最新版本。
有了該插件,您就可以開始資料庫遷移之旅了。 正如我所說,生產資料庫尚未建立。 您可以使用 "update" 的dbCreate值部署應用程式的初始版本,這將正常運作。 但是,由於我稍後將討論的原因,我想鼓勵您從資料庫遷移變更日誌(即遷移腳本)初始化資料庫。 別擔心,這比您想像的要少得多。
訣竅是使用插件的其中一個命令來為我們產生遷移腳本。 首先,請確保您的 'prod' 資料庫是空的,並刪除任何dbCreate用於該環境的設定。 然後執行
grails dbm-create-changelog grails prod dbm-generate-gorm-changelog --add changelog-1.0.groovy
(現在是嘗試新的 Grails 2 互動模式的好時機!)
以上將建立一個grails-app/migrations/changelog.groovy檔案,該檔案將成為您的父變更日誌檔案。 然後,第二個命令會產生一個遷移腳本,grails-app/migrations/changelog-1.0.groovy,它將採用一個空的資料庫,並為應用程式的目前版本建立適當的綱要。 父變更日誌也會更新以包含這個新的變更日誌。 請注意,您的資料庫將保持為空!
雖然 Liquibase 旨在與資料庫無關,但最好在配置了適當類型資料來源(通常為 "production")的 Grails 環境中執行各種產生和比較命令。 這將確保您不必對產生的變更日誌進行太多變更。
[callout title=變更日誌名稱] 該插件不會強制您對變更日誌檔案名使用任何特定的命名慣例。 在本文中,我只是使用 'changelog-
為什麼我們要建立 1.0 變更日誌,而不是使用 "update"dbCreate設定? 初始變更日誌表示您可以採用您的應用程式並將其部署到一個全新的空資料庫。 所有遷移都會如您預期的那樣運作,因為它們將從已知的固定綱要(即空綱要)按順序執行。 'update' 設定的問題在於,它將始終建立與目前網域模型匹配的綱要。 舊的變更日誌根本無法執行,因為資料庫並未處於它們期望的狀態! 如果您願意,仍然可以為您的第一個應用程式版本使用 "update",但上述方法意味著您有機會儘早測試您的初始變更日誌。
此時,請查看changelog-1.0.groovy檔案,以查看遷移的外觀以及是否需要變更任何內容。 您可能會看到添加了比您真正需要的更多索引和約束,因此可能需要進行一些修剪。
好的,所以我們現在有一個遷移腳本。 但是當我們運行grails prod run-app應用程式將無法啟動:資料庫仍然是空的。 為什麼? 遷移腳本不會在啟動時自動執行,這意味著您必須使用類似於dbm-update的命令手動更新資料庫,或者啟用啟動時的遷移執行。 我更喜歡後者,特別是因為在許多情況下,您根本無法從 Grails 命令列存取生產資料庫。 因此,將這些設定添加到Config.groovy檔案
grails.plugin.databasemigration.updateOnStart = true
grails.plugin.databasemigration.updateOnStartFileNames = ["changelog.groovy"]
現在,當您啟動應用程式時,遷移腳本將執行,您的應用程式將正常運作! 當您重新啟動伺服器時,該插件將檢測到遷移已經執行,因此它們將被忽略。
資料庫遷移的重點是,隨著應用程式的發展,您可以變更您的資料庫並控制該過程。 現在想像一下,您已經在應用程式上完成了一些工作,並且想要發布一個新版本,可能是 1.0.1。 若要升級生產資料庫,您將需要為您的網域模型變更建立一個變更日誌。 您可以手動執行此操作,但您可以透過使用資料庫遷移插件的 'diff' 命令來節省大量精力。
若要執行比較,您需要一個資料庫,該插件可以將目前的網域模型與之進行比較。 同樣,最好使用與您在生產環境中使用的資料庫類型相同的資料庫。 此外,資料庫必須處於其原始狀態,即在進行目前的網域模型變更之前。 換句話說,不要使用dbCreate = "update"啟用的情況下針對資料庫運行您的應用程式! 實際上,值得為應用程式的每個版本建立一個資料庫轉儲,以便您可以在以這種方式意外更新資料庫的情況下回滾。
好的,警告夠多了。 讓我們建立下一個變更日誌
grails prod dbm-gorm-diff --add changelog-1.0.1.groovy
與之前一樣,這將在遷移目錄中建立一個changelog-1.0.1.groovy檔案,並從父變更日誌中包含它。 您還需要檢查產生的變更日誌並可能進行調整,但編輯現有檔案比從頭建立一個新檔案容易得多。 就是這樣! 現在您可以將此變更日誌連同相應的網域類別變更提交到版本控制。 實際上,我建議您始終在同一次提交中包含網域類別變更和相應的遷移腳本修改。
變更日誌檔案本身看起來像這樣
databaseChangeLog = {
changeSet(id: "UpdateDescriminatorForPluginTabs", author: "pledbrook") {
update(tableName: "content") {
column name: "class", value: "org.grails.plugin.PluginTab"
where "title like 'description-%' and class = 'org.grails.wiki.WikiPage'"
}
}
changeSet(id: "IssuesUrlForPlugins", author: "pledbrook") {
addColumn(tableName: "plugin") {
column name: "issues_url", type: "varchar(255)", {
constraints nullable: true
}
}
}
}
如您所見,它們僅僅是變更集的集合,每個變更集包含一些資料庫重構。每個變更集都需要一個唯一的 ID (每個作者,每個變更日誌),以便 Liquibase 可以追蹤它是否已被應用(Liquibase 追蹤的是變更集,而不是變更日誌!)。上面的例子展示了如何更新現有資料(id "UpdateDescriminatorForPluginTabs"),以及如何新增一個新的欄位。其他支援的重構包括:
完整的重構範圍在 Liquibase 手冊中描述,儘管所有的例子都是 XML 格式。幸運的是,XML -> Groovy 的映射非常簡單:
最後,您可能想知道如何組織您的變更日誌。您應該為每個重構建立一個變更集嗎?還是每個變更日誌只建立一個變更集?還是介於兩者之間?這取決於您,但每個原始碼控制提交建立一個變更集可能效果不錯。換句話說,您為每個包含網域模型變更的提交建立一個變更集。或者,您可能希望每個資料庫表格建立一個變更集。做對您有效的方式即可。
這就是本文的全部內容。正如您所看到的,適當的資料庫遷移支援是任何生產資料庫支援的 Web 應用程式的重要組成部分,因此我們很高興現在有一個官方支援且功能非常強大的外掛程式來滿足這一需求。它僅適用於關聯式資料庫(所以恐怕沒有 Redis、MongoDB 等的遷移),但它仍然應該滿足絕大多數 Grails 使用者的需求。去試試看吧!