原始訴求
很多時候,我們在進行程式版本開發中,會遇到資料庫升級的情況,為了避擴音供給運維人員額外的sql檔案去執行,最好是由程式本身去完成該部分的任務(畢竟人為的事情不可控因素較多,因為人為升級資料庫造成的混亂、加班慘不忍睹……);最終的目標就是,將資料庫的變動全部變為sql,由本身的程式包(jar,war等)攜帶,在替換包的時候,資料庫會保證最新狀態。
程式結構設計
這裡,我採用java進行設計,整體的設計圖如下:
各個類的作用:
InitDataBase(介面):定義初始化所需功能
ExcuteActuator(介面):配置執行器,主要定義輔助升級過程中各類配置的獲取功能
AbstractInitDataBase(抽象類):實現了 InitDataBase和ExcuteActuator介面,是所有具體升級類的父類,指定了核心的資料庫升級步驟,完成了ExcuteActuator介面的大部分配置功能
MySqlDataBase(具體實現類):具體針對mysql資料庫進行升級的初始化類
這裡完成了整個程式的架子,目前僅實現了mysql的自動升級,後續有興趣,可以自動擴充Oracle等其他資料庫的升級過程,只需要繼承AbstractInitDataBase類,完成InitDataBase定義的功能即可。
github:https://github.com/GCC1566/Conscript
核心程式碼
public interface InitDataBase { /** * 資料庫初始化條件是否完成 * @return boolean */ boolean isInitEd(); /** * 核心任務 * 1、建立連結 * 2、是否可連結 * 3、是否存在庫 * 4、版本是否需要升級 */ void startCoreJob() throws SQLException; /** * 建立連結 * @return boolean */ boolean createConnection(); /** * 確認庫是否存在 * @return boolean */ boolean databaseIsExitd() throws SQLException; /** * 獲取當前資料庫版本 * @return */ Float getCurrenDbVersion() throws SQLException; /** * 執行sql內容 * @param sqlcontent * @return * @throws SQLDataException */ boolean excuteSQL(Map<String, String> sqlcontent) throws SQLDataException; /** * 關閉連線 * @return */ void close() throws SQLException; }
public abstract class AbstractInitDataBase implements InitDataBase { String DB_CONFIG_URL; public JSONArray dbconfig = new JSONArray(); public DbConConfiguration dbConConfiguration; public static Boolean flag = false; public AbstractInitDataBase(DbConConfiguration conConfiguration){ DB_CONFIG_URL = conConfiguration.getDbconfigfileurl(); dbConConfiguration = conConfiguration; } @Override public boolean isInitEd() { return flag; } @Override public void startCoreJob() throws SQLException { reloadConfigFile(); log.info("【資料庫初始化】開始基本資料庫初始化"); if(createConnection()){ log.info("【資料庫初始化】成功建立與資料庫的聯絡"); Map<String,String> sqlcontent; if(databaseIsExitd()) { //比對程式碼配置中所需資料庫版本是否大於當前資料庫中實際版本 if(getLatestVersion() > getCurrenDbVersion()) { log.info("【資料庫初始化】當前資料庫版本較低,進行資料庫升級"); sqlcontent = getSqlFromFile(getCurrenDbVersion()); }else { log.info("【資料庫初始化】當前資料庫已是最新版本"); flag = true; return; } }else{ log.info("【資料庫初始化】檢驗到本系統所需資料庫不存在,開啟自動建庫流程"); sqlcontent = getSqlFromFile(0f); } flag = excuteSQL(sqlcontent); }else{ log.error("【資料庫初始化】與資料庫服務建立連結失敗 ! 請確認資料庫服務是否正常或配置是否正確!"); } close(); } }
使用方式
引入Conscript
1.使用依賴引入
<dependency> <groupId>com.gcc</groupId> <artifactId>Conscript</artifactId> <version>1.0</version> </dependency>
由於暫未正式釋出,該方式僅限於本地編譯程式碼後釋出至本地私倉
2.直接引入程式碼
可在github上引用原始碼,將com.gcc.initdb目錄下的initdb包拷至程式碼中即可
3.使用jar包
將打包後的jar包引入專案,具體jar包留言私信即可
建立SQL檔案存放目錄
1.在resource目錄下新建sql目錄,裡面存放需要升級的sql檔案
2.在resource目錄下新建XX.json檔案作為配置檔案,XX.json檔案樣例如下:
mysql-dbconfig.json
[ { "version": "1.0", "sqlfile": "a.sql", "desc": "基礎資料庫結構" }, { "version": "1.1", "sqlfile": "ddd.sql", "desc": "第一版升級資料庫" } ]
意義 | |
---|---|
host | 資料庫服務ip地址 |
port | 資料庫服務埠 |
dbname | 資料庫名稱(需要初始化的庫名) |
user | 資料庫連線賬號 |
password | 資料庫連線密碼 |
dbconfigfileurl | 資料庫升級配置檔案 |
driverclassname | 資料庫連線驅動名稱 |
dbtype |
使用初始器工廠建立資料庫初始器
將DbConConfiguration物件作為DataBaseInitorFactory工廠方法的引數,生產資料庫初始器物件,進行資料庫初始化:
public static void main(String args[]){ DbConConfiguration conConfiguration = new DbConConfiguration.Builder() .setHost(cfgBean.getHost()) .setDbport(cfgBean.getDbport()) .setDbname(cfgBean.getDbname()) .setConfigFileUrl("mysql-dbconfig.json") .setDriverclassname(cfgBean.getDriverclassname()) .setDbtype(cfgBean.getDbtype().getDbtype()) .setUser(cfgBean.getUser()) .setPassword(cfgBean.getPassword()) .build(); InitDataBase initdb = DataBaseInitorFactory.createInitiator(conConfiguration); try { initdb.startCoreJob(); }catch (SQLException e){ log.error("資料庫錯誤"+e.getMessage()); } }