GreenDao3.0数据库升级保留原始数据的解决方法
2017-08-01 16:21
441 查看
/** * 数据库管理工具 */ public class DBManager { private DaoMaster.DevOpenHelper devOpenHelper; private static DBManager instance; private static final String DB_NAME = "test.db"; private DBManager() { devOpenHelper = new DBOpenHelper(MyApplication.getInstance(), DB_NAME); } public static DBManager getInstance() { if (instance == null) { instance = new DBManager(); } return instance; } public SQLiteDatabase getWritableDatabase() { if (devOpenHelper == null) { devOpenHelper = new DBOpenHelper(MyApplication.getInstance(), DB_NAME); } SQLiteDatabase db = devOpenHelper.getWritableDatabase(); return db; } }
/** * 实现GreenDao数据库升级保留原始交易数据 */ public class DBMigrationHelper { private static final String TAG = "DBMigrationHelper"; //DB中约束为NOT NULL的数据类型 List<Class> notNullClasses = Arrays.<Class>asList(boolean.class, byte.class, char.class, short.class, int.class, long.class, float.class, double.class, Boolean.class, Byte.class, Character.class, Short.class, Integer.class, Long.class, Float.class, Double.class); private Database db; private Collection<AbstractDao<?, ?>> allDaos; public DBMigrationHelper(SQLiteDatabase database) { db = new StandardDatabase(database); DaoMaster master = new DaoMaster(database); DaoSession session = master.newSession(IdentityScopeType.None); allDaos = session.getAllDaos(); } /** 更改表结构,将旧表数据导入新表 */ public void upgradeTablesScheme() { for (AbstractDao<?, ?> dao : allDaos) { @SuppressWarnings("unchecked") Class<? extends AbstractDao<?, ?>> daoCls = (Class<? extends AbstractDao<?, ?>>) dao.getClass(); handleUpgradeTableScheme(db, daoCls); } } /** 删除临时表 */ public void dropTempTables() { for (AbstractDao<?, ?> dao : allDaos) { @SuppressWarnings("unchecked") Class<? extends AbstractDao<?, ?>> daoCls = (Class<? extends AbstractDao<?, ?>>) dao.getClass(); dropTempTable(db, daoCls); } } /** 执行表结构变更 */ private void handleUpgradeTableScheme(Database db, Class<? extends AbstractDao<?, ?>> daoCls) { DaoConfig daoConfig = new DaoConfig(db, daoCls); String tableName = daoConfig.tablename; String tempTableName = tableName + "_TEMP"; //重命名表 db.execSQL("ALTER TABLE " + tableName + " RENAME TO " + tempTableName); //创建新表 createTable(daoCls, db, true); List<String> oldColumns = getColumns(db, tempTableName); List<String> shareColumns = new ArrayList<>(); List<String> newNotNullColumns = new ArrayList<>(); for (Property property : daoConfig.properties) { if (oldColumns.contains(property.columnName)) { shareColumns.add(property.columnName); } else if (checkNotNull(property)) { newNotNullColumns.add(property.columnName); } } //将旧表数据导入新表 String insertSQL = "INSERT INTO " + tableName + "(" + TextUtils.join(",", shareColumns); if (!newNotNullColumns.isEmpty()) { insertSQL += ","; insertSQL += TextUtils.join(",", newNotNullColumns); } insertSQL += ") SELECT "; insertSQL += TextUtils.join(",", shareColumns); String notNullStr = ""; for (String column : newNotNullColumns) { notNullStr += ",0 AS " + column; } insertSQL += notNullStr; insertSQL += " FROM " + tempTableName; db.execSQL(insertSQL); } /** 是否是非空列 */ private boolean checkNotNull(Property property) { return notNullClasses.contains(property.type); } /** 删除旧表 */ private void dropTempTable(Database db, Class<? extends AbstractDao<?, ?>> daoCls) { DaoConfig daoConfig = new DaoConfig(db, daoCls); String tableName = daoConfig.tablename; String tempTableName = tableName + "_TEMP"; //删除旧表 db.execSQL("DROP TABLE " + tempTableName); } /** 获取数据库所有列名称 */ private static List<String> getColumns(Database db, String tableName) { List<String> columns = new ArrayList<>(); Cursor cursor = null; try { cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null); if (cursor != null) { Collections.addAll(columns, cursor.getColumnNames()); } } catch (Exception e) { Log.v(tableName, e.getMessage(), e); e.printStackTrace(); } finally { if (cursor != null) { cursor.close(); } } return columns; } /** 创建表 */ private static void createTable(Class<? extends AbstractDao<?, ?>> daoCls, Database db, boolean b) { reflectMethod(daoCls, "createTable", db, b); } /** * 反射createTable或dropTable方法 */ private static void reflectMethod(@NonNull Class<? extends AbstractDao<?, ?>> daoCls, String methodName, Database db, boolean isExists) { try { Method method = daoCls.getDeclaredMethod(methodName, Database.class, boolean.class); method.invoke(null, db, isExists); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } /** 数据库升级接口,自定义升级时可实现本接口 */ public interface IDBMigration { void onMigrate(SQLiteDatabase db); } /** * <pre> * V35版本数据库升级类,升级内容如下: * </pre> */ public static class DBMigration_35 implements IDBMigration { @Override public void onMigrate(SQLiteDatabase db) { Database database = new StandardDatabase(db); //TODO 具体实现 } } /** * <pre> * V40版本数据库升级类,升级内容如下: * </pre> */ public static class DBMigration_40 implements IDBMigration { @Override public void onMigrate(SQLiteDatabase db) { //TODO 具体实现 } } }
/** * 数据库帮助类,重写了数据库升级操作,不删表保留原交易数据 */ public class DBOpenHelper extends DaoMaster.DevOpenHelper { private static final String TAG = "DBOpenHelper"; public DBOpenHelper(Context context, String name) { super(context, name); } @Override public void onCreate(SQLiteDatabase db) { DaoMaster.createAllTables(new StandardDatabase(db), false); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { try { if (newVersion > oldVersion) { //更改表结构 DBMigrationHelper helper = new DBMigrationHelper(db); helper.upgradeTablesScheme(); for (int i = oldVersion + 1; i <= newVersion; i++) { //获取不同数据库版本对应的迁移方法 //当用户跨版本升级时,依次执行每个版本对应的升级方法 Method method = getMigrationMethod(i); if (method != null) { method.invoke(this, db); } } //删除临时表 helper.dropTempTables(); } } catch (Exception e) { e.printStackTrace(); Log.e(TAG, "DB onUpgrade failed:" + e.getMessage()); } } /** * 获取数据库版本对应的迁移方法 * 数据库迁移方法命名格式为 migration_Scheme,其中 * Scheme为每个数据库版本的版本号 */ private Method getMigrationMethod(int version) { try { return getClass().getDeclaredMethod("migration_" + version, SQLiteDatabase.class); } catch (NoSuchMethodException e) { e.printStackTrace(); } return null; } /** V35版本数据库升级 */ @SuppressWarnings("unused") private void migration_35(SQLiteDatabase db) { IDBMigration migration = new DBMigration_35(); migration.onMigrate(db); } /** V40版本数据库升级 */ @SuppressWarnings("unused") private void migration_40(SQLiteDatabase db) { IDBMigration migration = new DBMigration_40(); migration.onMigrate(db); } }
相关文章推荐
- greendao3.0的使用, 以及数据库升级(保留原有数据), 和对应的sqlite写的方式
- greenDao3.0及以上数据库升级并保留原数据库数据,详细教程
- GreenDao3.0 使用(包括导入,具体方法,基本使用,加密,数据库升级等)
- GreenDAO 完美解决数据库升级数据丢失问题
- GreenDAO数据库升级问题的解决方法
- 物理删除oracle数据文件(DBF文件)导致数据库ORA-01033的解决方法
- ASE15.0.3升级时导致数据库不能启动问题的解决方法
- asp.net关于TextBox.Text的值为空时,将string数据插入到数据库中int数据的问题的解决方法
- DWH的保留原始历史数据的一种方法
- mysql jsp 解决乱码 创建数据库 数据表 方法
- 数据库时间段分组查询解决方法和数据转储方法
- 数据库连接方式读取不到Excel数据值的解决方法
- SharePoint 2010 Reporting Services 报表服务器无法解密用于访问报表服务器数据库中的敏感数据或加密数据的对称密钥 解决方法
- 物理删除oracle数据文件(DBF文件)导致数据库ORA-01033的解决方法
- PostgreSQL数据库不支持Geometry数据类型的解决方法
- T-SQL 语句插入中文数据时数据库显示全是问号“???”的解决方法(数据库编码规则)
- sql server 2005 中文件组的的概念及数据库文件因文件组满而无法写入的数据的解决方法
- [Excel Services]连接外部数据库,刷新数据的时候遇到“Data Refresh Failed ”的解决方法
- [转]数据库连接方式读取不到Excel数据值的解决方法
- SQL Server 2005“备份集中的数据库备份与现有的数据库不同”解决方法此信息转载自BlueSky's Blog,www.heuupk.com,为尊重无价的知识请保留此版权信息。