原始訴求
很多時候,我們在進行程序版本開發中,會遇到數據庫升級的情況,為了避免提供給運維人員額外的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()); } }