在使用SugarORM的時候,有可能在後期的工作中進行數據庫的升級操作。具體的操作參考:http://satyan.github.io/sugar/migration.html
文章鏈接:http://blog.csdn.net/lylddingHFFW/article/details/78230320
記錄:在進行數據庫升級時 注意
1)不支持select等返回數據集結果的語句;
2)在使用alter sql增加表中列的時候,如果Java文件中也增加同樣的字段,則會提示錯誤,增加重複列,後邊的分析會有提到;
3)assets的位置是在src/main/assets/;
public void doUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
List<Class> domainClasses = getDomainClasses(context);
String sql = "select count(*) from sqlite_master where type='table' and name='%s';";
for (Class domain : domainClasses) {
String tableName = NamingHelper.toSQLName(domain);
Cursor c = sqLiteDatabase.rawQuery(String.format(sql, tableName), null);
//判斷table是否存在,若存在,則檢查table中的columns。
if (c.moveToFirst() && c.getInt(0) == 0) {
createTable(domain, sqLiteDatabase);
} else {
addColumns(domain, sqLiteDatabase);
}
}
// 執行升級數據庫的sql文件。
executeSugarUpgrade(sqLiteDatabase, oldVersion, newVersion);
}
在addColumns中,檢查table中的columns。主要時比對Java文件中的屬性和數據庫 中table中的columns是否一直,若Java文件中有新增加的屬性,則拼接alter table 的sql。
private void addColumns(Class<?> table, SQLiteDatabase sqLiteDatabase) {
List<Field> fields = ReflectionUtil.getTableFields(table);
String tableName = NamingHelper.toSQLName(table);
ArrayList<String> presentColumns = getColumnNames(sqLiteDatabase, tableName);
ArrayList<String> alterCommands = new ArrayList<>();
for (Field column : fields) {
String columnName = NamingHelper.toSQLName(column);
String columnType = QueryBuilder.getColumnType(column.getType());
if (column.isAnnotationPresent(Column.class)) {
Column columnAnnotation = column.getAnnotation(Column.class);
columnName = columnAnnotation.name();
}
if (!presentColumns.contains(columnName)) {
//拼接 sql 語句
StringBuilder sb = new StringBuilder("ALTER TABLE ");
sb.append(tableName).append(" ADD COLUMN ").append(columnName).append(" ").append(columnType);
if (column.isAnnotationPresent(NotNull.class)) {
if (columnType.endsWith(" NULL")) {
sb.delete(sb.length() - 5, sb.length());
}
sb.append(" NOT NULL");
}
// Unique is not working on ALTER TABLE
// if (column.isAnnotationPresent(Unique.class)) {
// sb.append(" UNIQUE");
// }
alterCommands.add(sb.toString());
}
}
for (String command : alterCommands) {
Log.i("Sugar", command);
//執行 拼接的sql 語句。
sqLiteDatabase.execSQL(command);
}
}
executeSugarUpgrade函數中主要執行assets資源文件中的2.sql,3.sql等等。
private boolean executeSugarUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
boolean isSuccess = false;
try {
// 拿到assets中的sql文件名
List<String> files = Arrays.asList(this.context.getAssets().list("sugar_upgrades"));
Collections.sort(files, new NumberComparator());
for (String file : files) {
Log.i(SUGAR, "filename : " + file);
try {
int version = Integer.valueOf(file.replace(".sql", ""));
// 只會執行舊版本到新版本之間的sql文件
if ((version > oldVersion) && (version <= newVersion)) {
//執行sql文件
executeScript(db, file);
isSuccess = true;
}
} catch (NumberFormatException e) {
Log.i(SUGAR, "not a sugar script. ignored." + file);
}
}
} catch (IOException e) {
Log.e(SUGAR, e.getMessage());
}
return isSuccess;
}
執行sql腳本文件
private void executeScript(SQLiteDatabase db, String file) {
try {
//打開sql腳本資源
InputStream is = this.context.getAssets().open("sugar_upgrades/" + file);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
StringBuilder sb = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) {
sb.append(line);
}
MigrationFileParser migrationFileParser = new MigrationFileParser(sb.toString());
//以分號;來分割成不同的sql語句
for(String statement: migrationFileParser.getStatements()){
Log.i("Sugar script", statement);
if (!statement.isEmpty()) {
// 調用SqliteDatebase,來執行
db.execSQL(statement);
}
}
} catch (IOException e) {
Log.e(SUGAR, e.getMessage());
}
Log.i(SUGAR, "Script executed");
}