1. 程式人生 > >GreenDao的使用與資料庫升級------完整解析版

GreenDao的使用與資料庫升級------完整解析版

#GreenDao的使用

一、在project build.grade中新增:

dependencies {
        ......
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
    }

二、在app build.grade中新增:

......
apply plugin: 'org.greenrobot.greendao'

android {
    ......
    greendao {
        schemaVersion 1  //版本
        daoPackage 'dao' // 一般為app包名+生成檔案的資料夾名
        targetGenDir 'src/main/java' //生成檔案路徑
    }
}

dependencies {
    ......
    implementation 'org.greenrobot:greendao:3.2.2'
    implementation 'org.greenrobot:greendao-generator:3.2.2'    
}

 三、建立Dao類(以下為示例):

@Entity //必須新增
public class Student {
    @Id //標誌為主鍵
    private Long id;
    private String name;
    private String sex;
}

四、建立好Dao類(其成員變數對應著表的各個屬性)後,點選build,對專案進行構建,這時將生成一個第二步驟路徑的dao資料夾:

dao資料夾中包含:
   DaoMaster.class
   DaoSession.class
   StudentDao.class //由第三步驟中建立的Dao類決定

五、建立Application的子類,實現整個程式生命週期Context的獲取:

public class MApplication extends Application {

    private static Context mContext;

    @Override
    public void onCreate() {
        super.onCreate();
        mContext=this;
    }

    public static Context getContext() {
        return mContext;
    }
}

六、在AndroidMainifest.xml中註冊MApplication:

<application
        android:name=".MApplication"
        ......
    </application>

七、建立資料庫管理類、資料庫幫助類:

//資料庫幫助類
public class DatabaseHelper extends DaoMaster.OpenHelper {

    public DatabaseHelper(Context context, String name) {
        super(context, name);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        MigrationHelper.getInstance().migrate(db, StudentDao.class);
    }
}


//資料庫管理類
//這裡也可以學習一些單例模式的知識
public class DatabaseManager {

    private static DatabaseManager databaseManager;
    private static DatabaseHelper databaseHelper;
    private static DaoMaster daoMaster;
    private static DaoSession daoSession;

    public static DatabaseManager getInstance() {
        if(databaseManager==null) {
            synchronized (DatabaseManager.class) {
                if(databaseManager==null) {
                    databaseManager=new DatabaseManager();
                }
            }
        }
        return databaseManager;
    }

    public static DatabaseHelper getDatabaseHelper() {
        if(databaseHelper==null) {
            synchronized (DatabaseHelper.class) {
                if(databaseHelper==null) {
                    databaseHelper=new DatabaseHelper(MApplication.getContext(),"Student.db");
                }
            }
        }
        return databaseHelper;
    }

    public static DaoMaster getDaoMaster() {
        if(daoMaster==null) {
            synchronized (DaoMaster.class) {
                if(daoMaster==null) {
                    daoMaster=new DaoMaster(getDatabaseHelper().getWritableDatabase());
                }
            }
        }
        return daoMaster;
    }

    public static DaoSession getDaoSession() {
        if(daoSession==null) {
            synchronized (DaoSession.class) {
                if(daoSession==null) {
                    daoSession=getDaoMaster().newSession();
                }
            }
        }
        return daoSession;
    }
}

八、完成activity_main.xml和MainActivity.java:

//activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <LinearLayout
        android:id="@+id/ll_button"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:gravity="center"
        android:layout_marginTop="20dp">

        <TextView
            android:id="@+id/tv_add"
            android:layout_width="90dp"
            android:layout_height="35dp"
            android:text="Add"
            android:textSize="20sp"
            android:textStyle="bold"
            android:gravity="center"
            android:textColor="#FFFFFF"
            android:background="@drawable/textview_shape"/>

        <TextView
            android:id="@+id/tv_display"
            android:layout_width="90dp"
            android:layout_height="35dp"
            android:text="Show"
            android:textSize="20sp"
            android:textStyle="bold"
            android:gravity="center"
            android:textColor="#FFFFFF"
            android:layout_marginLeft="30dp"
            android:background="@drawable/textview_shape"/>

        <TextView
            android:id="@+id/tv_delete"
            android:layout_width="90dp"
            android:layout_height="35dp"
            android:text="Delete"
            android:textSize="20sp"
            android:textStyle="bold"
            android:gravity="center"
            android:textColor="#FFFFFF"
            android:layout_marginLeft="30dp"
            android:background="@drawable/textview_shape"/>
    </LinearLayout>

    <ScrollView
        android:layout_below="@+id/ll_button"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_marginTop="15dp">

        <TextView
            android:id="@+id/tv_show"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_margin="10dp"/>
    </ScrollView>
</RelativeLayout>



//MainActivty.java
public class MainActivity extends AppCompatActivity implements View.OnClickListener {

    private TextView addText,showText,deleteText,displayText;
    private List<Student> studentList=new ArrayList<>();
    private String text;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        addText=(TextView)findViewById(R.id.tv_add);
        deleteText=(TextView)findViewById(R.id.tv_delete);
        showText=(TextView)findViewById(R.id.tv_show);
        displayText=(TextView)findViewById(R.id.tv_display); 

        addText.setOnClickListener(this);
        deleteText.setOnClickListener(this);
        displayText.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.tv_add:
                for(int i=1;i<=5;++i) {
                    DatabaseManager.getInstance().getDaoSession().insert(new Student(null,"student"+i,"男"));
                }
                break;
            case R.id.tv_display:
                text="";
                studentList=DatabaseManager.getInstance().getDaoSession().getStudentDao().loadAll();
                for(Student student : studentList) {
                    text=text+student.getId()+"  "+student.getName()+"  "+student.getSex()+"\n";
                }
                showText.setText(text);
                break;
            case R.id.tv_delete:
                DatabaseManager.getInstance().getDaoSession().getStudentDao().deleteAll();
                text="";
                showText.setText(text);
                break;
        }
    }
}

以上步驟即可對GreenDao進行學習性使用

#GreenDao的資料庫升級

一、建立MigrationHelper類:

public class MigrationHelper {

    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

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

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {

        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }

    /**
     * 生成臨時列表
     *
     * @param db
     * @param daoClasses
     */
    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");

            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

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

            db.execSQL(insertTableStringBuilder.toString());

        }
    }

    /**
     * 儲存新的資料庫表 以及資料
     *
     * @param db
     * @param daoClasses
     */
    private 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");
            ArrayList<String> properties = new ArrayList();

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tempTableName).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(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();
            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class)) {
            return "BOOLEAN";
        }

        Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
        exception.printStackTrace();
        throw exception;
    }

    private 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) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }
}

二、編寫資料庫幫助類DatabaseHelper的onUpgrade方法 :

public class DatabaseHelper extends DaoMaster.OpenHelper {

   ......

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        MigrationHelper.getInstance().migrate(db, StudentDao.class);
    }
}

三、任意修改Dao類或新增新的Dao類

四、在app build.gradle中增加資料庫版本號,然後對專案進行build,即可實現對資料庫的升級:

android {
    ......
    greendao {
        schemaVersion 2  //版本號+1
        ......
    }
}

 以上步驟即可對GreenDao資料庫進行升級