Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> Android開發 >> 關於android開發 >> GreenDao 數據庫:使用Raw文件夾下的數據庫文件以及數據庫升級,greendaoraw

GreenDao 數據庫:使用Raw文件夾下的數據庫文件以及數據庫升級,greendaoraw

編輯:關於android開發

GreenDao 數據庫:使用Raw文件夾下的數據庫文件以及數據庫升級,greendaoraw


一、使用Raw文件夾下的數據庫文件

在使用GreenDao框架時,數據庫和數據表都是根據生成的框架代碼來自動創建的,從生成的DaoMaster中的OpenHelper類可以看出:

public static abstract class OpenHelper extends SQLiteOpenHelper {

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
       //修改第二個參數為true
createAllTables(db, false); } }

對應的createAllTables函數代碼:

/** Creates underlying database table using DAOs. */
    public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
        xxxxxDao.createTable(db, ifNotExists);
    }

再接著往下看:

/** Creates the underlying database table. */
    public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "'DOCTOR' (" + //
                "'_id' INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
                "'NAME' TEXT," + // 1: name
               
    }

從以上的代碼可以看出GreenDao在第一次使用的時候會強制創建數據表,如果這樣的話很可能就會導致程序崩潰。

public static abstract class OpenHelper extends SQLiteOpenHelper {

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
       //修改第二個參數為true

            createAllTables(db, true);
        }
    }

所以要使用Raw文件中的數據庫文件需要以下幾步:

  1)修改參數:

public static abstract class OpenHelper extends SQLiteOpenHelper {

        public OpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory, SCHEMA_VERSION);
        }

        @Override
        public void onCreate(SQLiteDatabase db) {
            Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
       //修改第二個參數為true

            createAllTables(db, true);
        }
    }

  2)添加GreenDaoContextWrapper.java文件到項目中

public class GreenDaoContextWrapper extends ContextWrapper {

private Context mContext;

public GreenDaoContextWrapper(Context base) {
super(base);
this.mContext= base;
}

@Override
public File getDatabasePath(String name) {
Log.d("GreenDao","getDatabasePath");
Log.d("GreenDao",mContext.getDatabasePath(name).getAbsolutePath());
String filePath=mContext.getDatabasePath(name).getAbsolutePath();
File file=new File(filePath);
if (!file.exists()){
buildDatabase(filePath);
}
return file;
}
  
/**
* 創建數據庫文件,其實就是將raw文件夾下的數據庫文件復制到應用的database文件夾下:
* /data/data/com.xxxx/databases/
* @param filePath
*/

private void buildDatabase(String filePath){
        Log.d("GreenDao","buildDatabase");
InputStream inputStream=mContext.getResources().openRawResource(R.raw.accurmedicine);
FileOutputStream fos= null;
try {
fos = new FileOutputStream(filePath);
byte[] buffer=new byte[1024];
int length;
while ((length=inputStream.read(buffer))>0){
fos.write(buffer,0,length);
}
fos.close();
inputStream.close();
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory) {
Log.d("GreenDao","openOrCreateDatabase");
SQLiteDatabase result= SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name),factory);
return result;
}

@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory, DatabaseErrorHandler errorHandler) {
Log.d("GreenDao","openOrCreateDatabase");
SQLiteDatabase result= SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name),factory);
return result;
}
}

這裡提一下:ContextWrapper是一個Context包裝類,需要包含一個真正的Context,詳細介紹看:

http://www.jianshu.com/p/94e0f9ab3f1d

  3)在創建DevOpenHelper的時候使用GreenDaoContextWrapper

String DBName="xxx";
DaoMaster.DevOpenHelper helper=new DaoMaster.DevOpenHelper(new GreenDaoContextWrapper(context),DBName,null);

這樣就大功告成了!

 

二、數據庫版本升級

這個辦法是從網上看到的,還不錯,就搬過來了。

public class MigrationHelper {

    private static MigrationHelper instance;

    public static MigrationHelper getInstance() {
        if (instance==null){
            instance=new MigrationHelper();
        }
        return instance;
    }

    /**
     * 創建臨時表->刪除舊表->創建新表->導入數據
     * @param database
     * @param daoClasses
     */
    public void migrate(SQLiteDatabase database, Class<? extends AbstractDao<?,?>>...daoClasses){
        generateTempTables(database,daoClasses);
        DaoMaster.dropAllTables(database,true);
        DaoMaster.createAllTables(database,false);
        restoreData(database,daoClasses);
    }

    /**
     * 臨時表生產
     * @param database
     * @param daoClasses
     */
    private void generateTempTables(SQLiteDatabase database,Class<? extends AbstractDao<?,?>>...daoClasses){
        for (int i=0;i<daoClasses.length;i++){
            DaoConfig config=new DaoConfig(database,daoClasses[i]);
            String divider="";
            String tableName=config.tablename;
            String tmpTableName=config.tablename.concat("_TEMP");
            ArrayList<String > properties=new ArrayList<>();
            StringBuilder createTableStringBuilder=new StringBuilder();
            createTableStringBuilder.append("CREATE TABLE ").append(tmpTableName).append(" (");
            List<String> columns = getColumns(database, tableName);
            for (int j=0;j<config.properties.length;j++){
                String columnName=config.properties[j].columnName;
                if (columns.contains(columnName)){
                    properties.add(columnName);
                    String type=null;
                    try {
                        type=getTypeByClass(config.properties[j].type);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);
                    if (config.properties[j].primaryKey){
                        createTableStringBuilder.append("  PRIMARY KEY");
                    }
                    divider=",";
                }
            }
            createTableStringBuilder.append(");");
            Log.d("xxxxx","sql="+createTableStringBuilder.toString());
            database.execSQL(createTableStringBuilder.toString());
            StringBuilder insertTableString=new StringBuilder();
            insertTableString.append("insert into ").append(tmpTableName).append(" (");
            insertTableString.append(TextUtils.join(",",properties));
            insertTableString.append(") select ");
            insertTableString.append(TextUtils.join(",",properties));
            insertTableString.append(" from ").append(tableName).append(";");
            Log.d("xxxxx","sql="+insertTableString.toString());
            database.execSQL(insertTableString.toString());
        }
    }

    /**
     * 數據字段與Java數據類型匹配
     * @param type
     * @return
     * @throws Exception
     */
    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)){
            return "TEXT";
        }
        if (type.equals(Long.class)||type.equals(Integer.class)){
            return "INTEGER";
        }
        if (type.equals(Boolean.class)){
            return "BOOLEAN";
        }
        String strException="數據表數據類型匹配錯誤";
        Exception exception=new Exception(strException.concat("- Class").concat(type.toString()));
        throw exception;
    }

    /**
     * 獲取當前數據表字段列表
     * @param database
     * @param tableName
     * @return
     */
    private static List<String > getColumns(SQLiteDatabase database,String tableName){
        List<String > columns=new ArrayList<>();
        Cursor cursor=null;
        /**
         * 通過查詢數據表
         */
        cursor=database.rawQuery("select * from "+tableName+" limit 1",null);
        try {
            if (cursor!=null){
                String[] columnNames = cursor.getColumnNames();
                for (String name:columnNames){
                    columns.add(name.toUpperCase());
                }
//                columns=new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            if (cursor!=null){
                cursor.close();
            }
        }
        return columns;
    }

    /**
     * 數據恢復->刪除臨時表
     * @param database
     * @param daoClasses
     */
    private void restoreData(SQLiteDatabase database,Class<? extends AbstractDao<?,?>>...daoClasses){
        for (int i=0;i<daoClasses.length;i++){
            DaoConfig config=new DaoConfig(database,daoClasses[i]);
            String tableName=config.tablename;
            String tmpTableName=config.tablename.concat("_TEMP");
            ArrayList<String > properties=new ArrayList<>();
            for (int j=0;j<config.properties.length;j++){
                String columnName = config.properties[j].columnName;

                if(getColumns(database, tmpTableName).contains(columnName)) {
                    properties.add(columnName);
                }
            }
            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tmpTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();

            dropTableStringBuilder.append("DROP TABLE ").append(tmpTableName);

            database.execSQL(insertTableStringBuilder.toString());
            database.execSQL(dropTableStringBuilder.toString());
        }
    }

}

 

然後在需要數據庫版本設計的時候修改DaoMaster中的SCHEMA_VERSION 

 

public static final int SCHEMA_VERSION = 1;

這個變量就是用於在創建OpenHelper時指定數據庫版本號。

緊接著修改DevOpenHelper的onUpgrade代碼:

 @Override
        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
//            dropAllTables(db, true);
//            onCreate(db);
            MigrationHelper.getInstance()
                    .migrate(db,
                    paramsDao.class,
                    );
        }

最後大功告成!

 順帶需要補充一下,查看SQLite數據庫版本可以執行以下這句語句:

 

PRAGMA user_version

 

設置SQLite數據庫版本的語句:

PRAGMA user_version =<你的版本號>

以上的這兩句話其實可以在SQLiteDatabase以及SQLiteOpenHelper的源碼中看到:

在android-24的SQLiteOpenHelper源碼中可以看到:

/**
     * Gets the database version.
     *
     * @return the database version
     */
    public int getVersion() {
        return ((Long) DatabaseUtils.longForQuery(this, "PRAGMA user_version;", null)).intValue();
    }

    /**
     * Sets the database version.
     *
     * @param version the new database version
     */
    public void setVersion(int version) {
        execSQL("PRAGMA user_version = " + version);
    }

而SQLiteOpenHelper設置和獲取數據庫版本就是通過調用這兩句話來實現的,具體源碼可以查看SQLiteOpenHelper的getDatabaseLocked函數,這裡不再贅述。

 

  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved