在网上找了很多资料,终于找到了Greendao数据库自定义路径,以及GreenDao数据库升级操作,避免开发阶段老是删除数据库,增删改查数据库都极其不方便,大部分是借鉴了网上的资料,然后自己做总结。
1,.修改DBUtil工具类,如下:
/** * 数据库工具类 * Created by pc on 2016/11/8. */ public class DBUtil { public static DaoSession getDaoSession(Context context) {
/* if (daoSession == null) { DaoMaster.OpenHelper openHelper = new DaoMaster.OpenHelper(context, "e6b") { @Override public void onUpgrade(Database db, int oldVersion, int newVersion) { switch (oldVersion) { case 1: db.beginTransaction(); db.execSQL("..."); db.setTransactionSuccessful(); db.endTransaction(); break; } } }; SQLiteDatabase db = openHelper.getWritableDatabase(); DaoMaster daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession();*/ return GreenDaoManager.getInstance().getSession();//换成自定义数据库操作类 } }2.添加几个工具类,GreenDaoManager.java(数据库模式管理类),MySQLiteOpenHelper.java(数据库模式选择类),MigrationHelper.java (数据备份升级类), GreenDaoContext.java (自定义数据库路径操作类) 分别如下:
public class GreenDaoManager { private DaoMaster mDaoMaster; private DaoSession mDaoSession; private static GreenDaoManager mInstance;//单例 private GreenDaoManager(){ if(mInstance==null) { // DaoMaster.DevOpenHelper devOpenHelper = new // DaoMaster.DevOpenHelper(MyApplication.getContext(), "database_name", null);//此处openhelper为自动生成开发所使用,发布版本需自定义 MySQLiteOpenHelper devOpenHelper =new MySQLiteOpenHelper(new GreenDaoContext(),"textGreendao.db", null);//GreenDaoContext为创建数据库路径使用
//数据库升级:数据库没有改变,默认1,1 数据库增加字段,删除字段,数据库有改变的,写1,2,表示数据库版本升级,数据库版本升级之后,原本数据库的数据不变 devOpenHelper.onUpgrade(devOpenHelper.getWritableDatabase(),1,2);//数据库有改动后,不会再崩mDaoMaster= new DaoMaster(devOpenHelper.getWritableDatabase()); mDaoSession= mDaoMaster.newSession(); } } public static GreenDaoManager getInstance() { if( mInstance== null) { synchronized(GreenDaoManager. class) { //保证异步处理安全操作 if( mInstance== null) { mInstance= new GreenDaoManager(); } } } return mInstance; } public DaoMaster getMaster() { return mDaoMaster; } public DaoSession getSession() { return mDaoSession; } public DaoSession getNewSession() { mDaoSession= mDaoMaster.newSession(); return mDaoSession; }}
public class MySQLiteOpenHelper extends DaoMaster.OpenHelper { public MySQLiteOpenHelper(Context context, String name) { super(context, name); } public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) { super(context, name, factory); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
if(oldVersion==newVersion){ return; }//数据迁移模块 MigrationHelper. migrate(db, TestInfoDao. class); }}
public class MigrationHelper { public static boolean DEBUG = true; private static String TAG = "MigrationHelper"; private static final String SQLITE_MASTER = "sqlite_master"; private static final String SQLITE_TEMP_MASTER = "sqlite_temp_master"; public static void migrate(SQLiteDatabase db, Class extends AbstractDao, ?>>... daoClasses) { Database database = new StandardDatabase(db); Log.e("MigrationHelper-->", "【The Old Database Version】" + db.getVersion()); Log.e("MigrationHelper-->", "【Generate temp table】start"); generateTempTables(database, daoClasses); Log.e("MigrationHelper-->", "【Generate temp table】complete"); dropAllTables(database, true, daoClasses); createAllTables(database, false, daoClasses); Log.e("MigrationHelper-->", "【Restore data】start"); restoreData(database, daoClasses); Log.e("MigrationHelper-->", "【Restore data】complete"); } private static void generateTempTables(Database db, Class extends AbstractDao, ?>>... daoClasses) { for (int i = 0; i < daoClasses.length; i++) { String tempTableName = null; DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); String tableName = daoConfig.tablename; if (!isTableExists(db, false, tableName)) {//不存在系统表中,表明是新增表,不需要创建临时表 Log.e("MigrationHelper-->", "【New Table】" + tableName); continue; } try { tempTableName = daoConfig.tablename.concat("_TEMP"); StringBuilder dropTableStringBuilder = new StringBuilder(); dropTableStringBuilder.append("DROP TABLE IF EXISTS ").append(tempTableName).append(";"); db.execSQL(dropTableStringBuilder.toString()); StringBuilder insertTableStringBuilder = new StringBuilder(); insertTableStringBuilder.append("CREATE TEMPORARY TABLE ").append(tempTableName); insertTableStringBuilder.append(" AS SELECT * FROM ").append(tableName).append(";"); db.execSQL(insertTableStringBuilder.toString()); Log.e("MigrationHelper-->", "【Table】" + tableName + "\n ---Columns-->" + getColumnsStr(daoConfig)); Log.e("MigrationHelper-->", "【Generate temp table】" + tempTableName); } catch (SQLException e) { Log.e(TAG, "【Failed to generate temp table】" + tempTableName, e); } } } private static boolean isTableExists(Database db, boolean isTemp, String tableName) { if (db == null || TextUtils.isEmpty(tableName)) { return false; } String dbName = isTemp ? SQLITE_TEMP_MASTER : SQLITE_MASTER; String sql = "SELECT COUNT(*) FROM " + dbName + " WHERE type = ? AND name = ?"; Cursor cursor = null; int count = 0; try { cursor = db.rawQuery(sql, new String[]{"table", tableName}); if (cursor == null || !cursor.moveToFirst()) { return false; } count = cursor.getInt(0); } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) cursor.close(); } return count > 0; } private static String getColumnsStr(DaoConfig daoConfig) { if (daoConfig == null) { return "no columns"; } StringBuilder builder = new StringBuilder(); for (int i = 0; i < daoConfig.allColumns.length; i++) { builder.append(daoConfig.allColumns[i]); builder.append(","); } if (builder.length() > 0) { builder.deleteCharAt(builder.length() - 1); } return builder.toString(); } private static void dropAllTables(Database db, boolean ifExists, @NonNull Class extends AbstractDao, ?>>... daoClasses) { reflectMethod(db, "dropTable", ifExists, daoClasses); printLog("【Drop all table】"); } private static void createAllTables(Database db, boolean ifNotExists, @NonNull Class extends AbstractDao, ?>>... daoClasses) { reflectMethod(db, "createTable", ifNotExists, daoClasses); printLog("【Create all table】"); } /** * dao class already define the sql exec method, so just invoke it */ private static void reflectMethod(Database db, String methodName, boolean isExists, @NonNull Class extends AbstractDao, ?>>... daoClasses) { if (daoClasses.length < 1) { return; } try { for (Class cls : daoClasses) { Method method = cls.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(); } } private static void restoreData(Database db, Class extends AbstractDao, ?>>... daoClasses) { for (int i = 0; i < daoClasses.length; i++) { DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); String tableName = daoConfig.tablename; String tempTableName = daoConfig.tablename.concat("_TEMP"); if (!isTableExists(db, true, tempTableName)) { continue; } try { // get all columns from tempTable, take careful to use the columns list Listcolumns = getColumns(db, tempTableName); ArrayList properties = new ArrayList<>(columns.size()); for (int j = 0; j < daoConfig.properties.length; j++) { String columnName = daoConfig.properties[j].columnName; if (columns.contains(columnName)) { properties.add(columnName); } } if (properties.size() > 0) { final String columnSQL = TextUtils.join(",", properties); StringBuilder insertTableStringBuilder = new StringBuilder(); insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" ("); insertTableStringBuilder.append(columnSQL); insertTableStringBuilder.append(") SELECT "); insertTableStringBuilder.append(columnSQL); insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); db.execSQL(insertTableStringBuilder.toString()); printLog("【Restore data】 to " + tableName); } StringBuilder dropTableStringBuilder = new StringBuilder(); dropTableStringBuilder.append("DROP TABLE ").append(tempTableName); db.execSQL(dropTableStringBuilder.toString()); printLog("【Drop temp table】" + tempTableName); } catch (SQLException e) { Log.e(TAG, "【Failed to restore data from temp table 】" + tempTableName, e); } } } private static List getColumns(Database db, String tableName) { List columns = null; Cursor cursor = null; try { cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 0", null); if (null != cursor && cursor.getColumnCount() > 0) { columns = Arrays.asList(cursor.getColumnNames()); } } catch (Exception e) { e.printStackTrace(); } finally { if (cursor != null) cursor.close(); if (null == columns) columns = new ArrayList<>(); } return columns; } private static void printLog(String info){ if(DEBUG){ Log.d(TAG, info); } } }
public class GreenDaoContext extends ContextWrapper { private String currentUserId = "greendao";//一般用来针对一个用户一个数据库,以免数据混乱问题 private Context mContext; public GreenDaoContext() { super(Myapplication.getContext()); this.mContext = Myapplication.getContext(); // this.currentUserId = "greendao";//初始化 } /** * 获得数据库路径,如果不存在,则创建对象 * * @param dbName */ @Override public File getDatabasePath(String dbName) { String dbDir = FilePathUtil.getDBDir();//外置sd卡路径 if (TextUtils.isEmpty(dbDir)){ dbDir = FilePathUtil.getInnerSDCardPath();//没外置,存内置 } Log.e("SD卡管理:", "dbDir="+dbDir); File baseFile = new File(dbDir); // 目录不存在则自动创建目录 if (!baseFile.exists()) { baseFile.mkdirs(); Log.e("SD卡管理:", "dbDir="+dbDir); } StringBuffer buffer = new StringBuffer(); buffer.append(baseFile.getPath()); buffer.append(File.separator); //buffer.append(currentUserId); dbDir = buffer.toString();// 数据库所在目录 buffer.append(File.separator); // buffer.append(dbName+"_"+currentUserId);//也可以采用此种方式,将用户id与表名联系到一块命名 buffer.append(dbName); String dbPath = buffer.toString();// 数据库路径 // 判断目录是否存在,不存在则创建该目录 File dirFile = new File(dbDir); if (!dirFile.exists()) { dirFile.mkdirs(); Log.e("SD卡管理:", "dbDir="+dbDir); } // 数据库文件是否创建成功 boolean isFileCreateSuccess = false; // 判断文件是否存在,不存在则创建该文件 File dbFile = new File(dbPath); if (!dbFile.exists()) { try { isFileCreateSuccess = dbFile.createNewFile();// 创建文件 Log.e("SD卡管理:", "dbPath="+dbPath); } catch (IOException e) { e.printStackTrace(); } } else isFileCreateSuccess = true; // 返回数据库文件对象 if (isFileCreateSuccess) return dbFile; else return super.getDatabasePath(dbName); } /** * 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。 * * @param name * @param mode * @param factory */ @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) { SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory); return result; } /** * Android 4.0会调用此方法获取数据库。 * * @param name * @param mode * @param factory * @param errorHandler * @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int, * android.database.sqlite.SQLiteDatabase.CursorFactory, * android.database.DatabaseErrorHandler) */ @Override public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) { SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory); return result; } }
最后还是一样的调用DBUtil,获取相应的Dao
TestInfoDao mDao=DBUtil.getDaoSession(context).getTestInfoDao();
不明白的可以看我之前的博客 Android studio,使用greenDao第三方数据库框架操作数据库
联系起来就可以了
我的demo已上传
这样就O啦
我不是个呆若木鸡的小小英