数据库操作能力 -- GreenDao -- 2

2020-01-09  本文已影响0人  TomyZhang

七、数据库的升级

GreenDao的OpenHelper下有个onUpgrade(Database db, int oldVersion, int newVersion)方法,当设置的数据库版本改变时,在数据库初始化的时候就会回调到这个方法,我们可以通过继承OpenHelper重写onUpgrade方法来实现数据库更新操作。

数据库的升级思路:

//build.gradle(module)
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.0"
    defaultConfig {
        applicationId "com.example.sourcecodetest"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation 'org.greenrobot:greendao:3.2.2' // add library
}

greendao {
    schemaVersion 5 //数据库版本号,原本为3改为5,用于测试数据库升级
    daoPackage 'com.example.sourcecodetest.database'
    //设置DaoMaster、DaoSession、Dao包名
    targetGenDir 'src/main/java' //设置DaoMaster、DaoSession、Dao目录,请注意,这里路径用 / 不要用 .
    generateTests false //设置为true以自动生成单元测试
    targetGenDirTests 'src/main/java' //应存储生成的单元测试的基本目录。默认为src/androidTest/java
}

//MyApplication
public class MyApplication extends Application {
    private static final String TAG = "MyApplication";
    private DaoSession daoSession;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "zwm, onCreate");
        initGreenDao();
    }

    /**
     * 初始化GreenDao,直接在Application中进行初始化操作
     */
    private void initGreenDao() {
        Log.d(TAG, "zwm, initGreenDao");
        //DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "tomorrow.db");
        MyDaoMaster helper = new MyDaoMaster(this, "tomorrow.db"); //自定义DaoMaster.OpenHelper,用于处理数据库升级
        SQLiteDatabase db = helper.getWritableDatabase();
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }
}

//MyDaoMaster
public class MyDaoMaster extends DaoMaster.OpenHelper {
    private static final String TAG = "MyDaoMaster";

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

    public MyDaoMaster(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
        Log.d(TAG, "zwm, onUpgrade oldVersion: " + oldVersion + " newVersion: " + newVersion);
        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {
            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                Log.d(TAG, "zwm, onCreateAllTables, ifNotExists: " + ifNotExists);
                DaoMaster.createAllTables(db, ifNotExists);
            }
            @Override
            public void onDropAllTables(Database db, boolean ifExists) {
                Log.d(TAG, "zwm, onDropAllTables, ifExists: " + ifExists);
                DaoMaster.dropAllTables(db, ifExists);
            }
        }, StudentDao.class, TeacherDao.class, StudentAndTeacherBeanDao.class);
    }
}

//MigrationHelper
public final 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";

    private static WeakReference<ReCreateAllTableListener> weakListener;

    public interface ReCreateAllTableListener{
        void onCreateAllTables(Database db, boolean ifNotExists);
        void onDropAllTables(Database db, boolean ifExists);
    }

    public static void migrate(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        printLog("【The Old Database Version】" + db.getVersion());
        Database database = new StandardDatabase(db);
        migrate(database, daoClasses);
    }

    public static void migrate(SQLiteDatabase db, ReCreateAllTableListener listener, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        weakListener = new WeakReference<>(listener);
        migrate(db, daoClasses);
    }

    public static void migrate(Database database, ReCreateAllTableListener listener, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        weakListener = new WeakReference<>(listener);
        migrate(database, daoClasses);
    }

    public static void migrate(Database database, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        printLog("【Generate temp table】start");
        generateTempTables(database, daoClasses);
        printLog("【Generate temp table】complete");

        ReCreateAllTableListener listener = null;
        if (weakListener != null) {
            listener = weakListener.get();
        }

        if (listener != null) {
            listener.onDropAllTables(database, true);
            printLog("【Drop all table by listener】");
            listener.onCreateAllTables(database, false);
            printLog("【Create all table by listener】");
        } else {
            dropAllTables(database, true, daoClasses);
            createAllTables(database, false, daoClasses);
        }
        printLog("【Restore data】start");
        restoreData(database, daoClasses);
        printLog("【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)) {
                printLog("【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());
                printLog("【Table】" + tableName +"\n ---Columns-->"+getColumnsStr(daoConfig));
                printLog("【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 by reflect】");
    }

    private static void createAllTables(Database db, boolean ifNotExists, @NonNull Class<? extends AbstractDao<?, ?>>... daoClasses) {
        reflectMethod(db, "createTable", ifNotExists, daoClasses);
        printLog("【Create all table by reflect】");
    }

    /**
     * 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
                List<TableInfo> newTableInfos = TableInfo.getTableInfo(db, tableName);
                List<TableInfo> tempTableInfos = TableInfo.getTableInfo(db, tempTableName);
                ArrayList<String> selectColumns = new ArrayList<>(newTableInfos.size());
                ArrayList<String> intoColumns = new ArrayList<>(newTableInfos.size());
                for (TableInfo tableInfo : tempTableInfos) {
                    if (newTableInfos.contains(tableInfo)) {
                        String column = '`' + tableInfo.name + '`';
                        intoColumns.add(column);
                        selectColumns.add(column);
                    }
                }
                // NOT NULL columns list
                for (TableInfo tableInfo : newTableInfos) {
                    if (tableInfo.notnull && !tempTableInfos.contains(tableInfo)) {
                        String column = '`' + tableInfo.name + '`';
                        intoColumns.add(column);

                        String value;
                        if (tableInfo.dfltValue != null) {
                            value = "'" + tableInfo.dfltValue + "' AS ";
                        } else {
                            value = "'' AS ";
                        }
                        selectColumns.add(value + column);
                    }
                }

                if (intoColumns.size() != 0) {
                    StringBuilder insertTableStringBuilder = new StringBuilder();
                    insertTableStringBuilder.append("REPLACE INTO ").append(tableName).append(" (");
                    insertTableStringBuilder.append(TextUtils.join(",", intoColumns));
                    insertTableStringBuilder.append(") SELECT ");
                    insertTableStringBuilder.append(TextUtils.join(",", selectColumns));
                    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<String> getColumns(Database db, String tableName) {
        List<String> 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, "zwm, " + info);
        }
    }

    private static class TableInfo {
        int cid;
        String name;
        String type;
        boolean notnull;
        String dfltValue;
        boolean pk;

        @Override
        public boolean equals(Object o) {
            return this == o
                    || o != null
                    && getClass() == o.getClass()
                    && name.equals(((TableInfo) o).name);
        }

        @Override
        public String toString() {
            return "TableInfo{" +
                    "cid=" + cid +
                    ", name='" + name + '\'' +
                    ", type='" + type + '\'' +
                    ", notnull=" + notnull +
                    ", dfltValue='" + dfltValue + '\'' +
                    ", pk=" + pk +
                    '}';
        }

        private static List<TableInfo> getTableInfo(Database db, String tableName) {
            String sql = "PRAGMA table_info(" + tableName + ")";
            printLog(sql);
            Cursor cursor = db.rawQuery(sql, null);
            if (cursor == null)
                return new ArrayList<>();
            TableInfo tableInfo;
            List<TableInfo> tableInfos = new ArrayList<>();
            while (cursor.moveToNext()) {
                tableInfo = new TableInfo();
                tableInfo.cid = cursor.getInt(0);
                tableInfo.name = cursor.getString(1);
                tableInfo.type = cursor.getString(2);
                tableInfo.notnull = cursor.getInt(3) == 1;
                tableInfo.dfltValue = cursor.getString(4);
                tableInfo.pk = cursor.getInt(5) == 1;
                tableInfos.add(tableInfo);
                // printLog(tableName + ":" + tableInfo);
            }
            cursor.close();
            return tableInfos;
        }
    }
}

//Student
@Entity
public class Student {
    @Id(autoincrement = true)
    private Long id;

    @Unique
    private long studentNo; //学号

    private int age; //年龄

    private String telPhone; //手机号

    private String sex; //性别

    private String name; //姓名

    private  String address; //家庭住址

    private String schoolName; //学校名字

    private String grade; //几年级

    private boolean addNewField; //增加的新列,用于测试数据库升级

    @ToMany
    @JoinEntity(entity = StudentAndTeacherBean.class,sourceProperty = "studentId",targetProperty = "teacherId")
    List<Teacher> teacherList;
}

//MainActivity
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "zwm, onCreate");

        //insert(); //插入数据后注释掉,用于测试数据库升级
        List<Student> list = loadStudents();
        for(Student student : list) {
            Log.d(TAG, "zwm, student NO." + student.getStudentNo() + ", _id: " + student.getId() + ", age: " + student.getAge() + ", name: " + student.getName());
            Log.d(TAG, "zwm, student newField: " + student.getAddNewField());
            List<Teacher> teacherList = student.getTeacherList();
            Log.d(TAG, "zwm, teacherList.size: " + teacherList.size());
            if(teacherList != null && teacherList.size() > 0) {
                for(Teacher teacher : teacherList) {
                    Log.d(TAG, "zwm, teacher NO." + teacher.getTeacherNo() + ", _id: " + teacher.getId() + ", age: " + teacher.getAge() + ", name: " + teacher.getName());
                }
            }
        }

        List<Teacher> list2 = loadTeachers();
        for(Teacher teacher : list2) {
            Log.d(TAG, "zwm, teacher NO." + teacher.getTeacherNo() + ", _id: " + teacher.getId() + ", age: " + teacher.getAge() + ", name: " + teacher.getName());
            List<Student> studentList = teacher.getStudentList();
            Log.d(TAG, "zwm, studentList.size: " + studentList.size());
            if(studentList != null && studentList.size() > 0) {
                for(Student student : studentList) {
                    Log.d(TAG, "zwm, student NO." + student.getStudentNo() + ", _id: " + student.getId() + ", age: " + student.getAge() + ", name: " + student.getName());
                }
            }
        }
    }

    public void insert() {
        Log.d(TAG, "zwm, insert");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        Student student = new Student();
        student.setStudentNo(5551);
        student.setAge(18);
        student.setTelPhone("5524307");
        student.setName("学生1");
        student.setSex("男");
        student.setAddress("广州");
        student.setGrade("一");
        student.setSchoolName("大学");
        daoSession.insert(student);

        Student student2 = new Student();
        student2.setStudentNo(5552);
        student2.setAge(19);
        student2.setTelPhone("5524308");
        student2.setName("学生2");
        student2.setSex("男");
        student2.setAddress("深圳");
        student2.setGrade("二");
        student2.setSchoolName("大学");
        daoSession.insert(student2);

        Student student3 = new Student();
        student3.setStudentNo(5553);
        student3.setAge(20);
        student3.setTelPhone("5524309");
        student3.setName("学生3");
        student3.setSex("男");
        student3.setAddress("北京");
        student3.setGrade("三");
        student3.setSchoolName("大学");
        daoSession.insert(student3);

        Teacher teacher1 = new Teacher();
        teacher1.setTeacherNo(9991);
        teacher1.setAge(28);
        teacher1.setTelPhone("9924307");
        teacher1.setName("教师1");
        teacher1.setSex("男");
        teacher1.setSubject("语文");
        teacher1.setSchoolName("大学");
        daoSession.insert(teacher1);

        Teacher teacher2 = new Teacher();
        teacher2.setTeacherNo(9992);
        teacher2.setAge(29);
        teacher2.setTelPhone("9924308");
        teacher2.setName("教师2");
        teacher2.setSex("男");
        teacher2.setSubject("数学");
        teacher2.setSchoolName("大学");
        daoSession.insert(teacher2);

        Teacher teacher3 = new Teacher();
        teacher3.setTeacherNo(9993);
        teacher3.setAge(30);
        teacher3.setTelPhone("9924309");
        teacher3.setName("教师3");
        teacher3.setSex("男");
        teacher3.setSubject("英语");
        teacher3.setSchoolName("大学");
        daoSession.insert(teacher3);

        StudentAndTeacherBean studentAndTeacher = new StudentAndTeacherBean();
        studentAndTeacher.setStudentId(Long.valueOf(1));
        studentAndTeacher.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher);

        StudentAndTeacherBean studentAndTeacher2 = new StudentAndTeacherBean();
        studentAndTeacher2.setStudentId(Long.valueOf(1));
        studentAndTeacher2.setTeacherId(Long.valueOf(2));
        daoSession.insert(studentAndTeacher2);

        StudentAndTeacherBean studentAndTeacher3 = new StudentAndTeacherBean();
        studentAndTeacher3.setStudentId(Long.valueOf(2));
        studentAndTeacher3.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher3);

        StudentAndTeacherBean studentAndTeacher4 = new StudentAndTeacherBean();
        studentAndTeacher4.setStudentId(Long.valueOf(2));
        studentAndTeacher4.setTeacherId(Long.valueOf(3));
        daoSession.insert(studentAndTeacher4);

        StudentAndTeacherBean studentAndTeacher5 = new StudentAndTeacherBean();
        studentAndTeacher5.setStudentId(Long.valueOf(3));
        studentAndTeacher5.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher5);

        StudentAndTeacherBean studentAndTeacher6 = new StudentAndTeacherBean();
        studentAndTeacher6.setStudentId(Long.valueOf(3));
        studentAndTeacher6.setTeacherId(Long.valueOf(2));
        daoSession.insert(studentAndTeacher6);

        StudentAndTeacherBean studentAndTeacher7 = new StudentAndTeacherBean();
        studentAndTeacher7.setStudentId(Long.valueOf(3));
        studentAndTeacher7.setTeacherId(Long.valueOf(3));
        daoSession.insert(studentAndTeacher7);
    }

    public List<Student> loadStudents(){
        Log.d(TAG, "zwm, loadStudents");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        List<Student> students = daoSession.loadAll(Student.class);
        return students;
    }

    public List<Teacher> loadTeachers(){
        Log.d(TAG, "zwm, loadTeachers");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        List<Teacher> teachers = daoSession.loadAll(Teacher.class);
        return teachers;
    }
}

//输出log
2020-01-08 19:45:42.461 29277-29277/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-08 19:45:42.461 29277-29277/com.example.sourcecodetest D/MyApplication: zwm, initGreenDao
2020-01-08 19:45:42.889 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-08 19:45:42.889 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, insert
2020-01-08 19:45:43.046 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, loadStudents
2020-01-08 19:45:43.051 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:45:43.051 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:45:43.061 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 19:45:43.061 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:45:43.062 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:45:43.062 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:45:43.062 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:45:43.067 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 19:45:43.068 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:45:43.068 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:45:43.068 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:45:43.069 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:45:43.072 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 3
2020-01-08 19:45:43.072 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:45:43.072 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:45:43.072 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:45:43.072 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, loadTeachers
2020-01-08 19:45:43.076 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:45:43.080 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 3
2020-01-08 19:45:43.080 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:45:43.080 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:45:43.080 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:45:43.080 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:45:43.084 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 19:45:43.085 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:45:43.085 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:45:43.085 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:45:43.088 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 19:45:43.088 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:45:43.088 29277-29277/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:49:37.030 30214-30214/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-08 19:49:37.030 30214-30214/com.example.sourcecodetest D/MyApplication: zwm, initGreenDao
2020-01-08 19:49:37.153 30214-30214/com.example.sourcecodetest D/MyDaoMaster: zwm, onUpgrade oldVersion: 3 newVersion: 5
2020-01-08 19:49:37.154 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Generate temp table】start
2020-01-08 19:49:37.167 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Table】STUDENT
     ---Columns-->_id,STUDENT_NO,AGE,TEL_PHONE,SEX,NAME,ADDRESS,SCHOOL_NAME,GRADE,ADD_NEW_FIELD
2020-01-08 19:49:37.167 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Generate temp table】STUDENT_TEMP
2020-01-08 19:49:37.173 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Table】TEACHER
     ---Columns-->_id,TEACHER_NO,AGE,SEX,TEL_PHONE,NAME,SCHOOL_NAME,SUBJECT
2020-01-08 19:49:37.174 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Generate temp table】TEACHER_TEMP
2020-01-08 19:49:37.186 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Table】STUDENT_AND_TEACHER_BEAN
     ---Columns-->_id,STUDENT_ID,TEACHER_ID
2020-01-08 19:49:37.186 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Generate temp table】STUDENT_AND_TEACHER_BEAN_TEMP
2020-01-08 19:49:37.186 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Generate temp table】complete
2020-01-08 19:49:37.186 30214-30214/com.example.sourcecodetest D/MyDaoMaster: zwm, onDropAllTables, ifExists: true
2020-01-08 19:49:37.195 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Drop all table by listener】
2020-01-08 19:49:37.196 30214-30214/com.example.sourcecodetest D/MyDaoMaster: zwm, onCreateAllTables, ifNotExists: false
2020-01-08 19:49:37.202 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Create all table by listener】
2020-01-08 19:49:37.202 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Restore data】start
2020-01-08 19:49:37.205 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(STUDENT)
2020-01-08 19:49:37.208 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(STUDENT_TEMP)
2020-01-08 19:49:37.212 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Restore data】 to STUDENT
2020-01-08 19:49:37.213 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Drop temp table】STUDENT_TEMP
2020-01-08 19:49:37.216 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(TEACHER)
2020-01-08 19:49:37.220 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(TEACHER_TEMP)
2020-01-08 19:49:37.228 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Restore data】 to TEACHER
2020-01-08 19:49:37.230 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Drop temp table】TEACHER_TEMP
2020-01-08 19:49:37.233 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(STUDENT_AND_TEACHER_BEAN)
2020-01-08 19:49:37.237 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, PRAGMA table_info(STUDENT_AND_TEACHER_BEAN_TEMP)
2020-01-08 19:49:37.241 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Restore data】 to STUDENT_AND_TEACHER_BEAN
2020-01-08 19:49:37.242 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Drop temp table】STUDENT_AND_TEACHER_BEAN_TEMP
2020-01-08 19:49:37.242 30214-30214/com.example.sourcecodetest D/MigrationHelper: zwm, 【Restore data】complete
2020-01-08 19:49:37.591 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-08 19:49:37.592 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, loadStudents
2020-01-08 19:49:37.598 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:49:37.598 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:49:37.608 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 19:49:37.608 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:49:37.608 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:49:37.608 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:49:37.608 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:49:37.612 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 19:49:37.612 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:49:37.612 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:49:37.612 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:49:37.612 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 19:49:37.616 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 3
2020-01-08 19:49:37.617 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:49:37.617 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:49:37.617 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:49:37.618 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, loadTeachers
2020-01-08 19:49:37.623 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 19:49:37.628 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 3
2020-01-08 19:49:37.632 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:49:37.632 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:49:37.633 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:49:37.633 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 19:49:37.637 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 19:49:37.637 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 19:49:37.637 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 19:49:37.637 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 19:49:37.641 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 19:49:37.641 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 19:49:37.641 30214-30214/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3

自定义SQLiteOpenHelper处理数据库升级(用于参考)

//MusicDBHelper
final class MusicDBHelper extends SQLiteOpenHelper {

    private static final String TAG = MusicProvider.class.getSimpleName();

    final Context mContext;

    /*
     * naming style 50 001 OS version local version.
     */
    public static final int DATABASE_VERSION = 20091;

    private static volatile MusicDBHelper sInstance;

    public static synchronized MusicDBHelper getInstance(Context context) {
        if (sInstance == null) {
            synchronized (MusicDBHelper.class) {
                if (sInstance == null) {
                    sInstance = new MusicDBHelper(context);
                }
            }
        }
        return sInstance;
    }

    private MusicDBHelper(Context context) {
        super(context, MusicDBInfo.PRIMARY_DATABASE_NAME, null, DATABASE_VERSION);
        mContext = context;
        iLog.d("MusicDBHelper", "()");
    }

    @Override
    public void onCreate(final SQLiteDatabase db) {
        iLog.d("MusicDBHelper", "onCreate");
        updateDatabase(mContext, db, 0, DATABASE_VERSION);
    }

    @Override
    public void onUpgrade(final SQLiteDatabase db, final int oldVersion, final int newVersion) {
        iLog.d("MusicDBHelper",
                "onUpgrade : oldVersion = " + oldVersion + ", newVersion = " + newVersion);
        updateDatabase(mContext, db, oldVersion, newVersion);
    }

    /**
     * This method takes care of updating all the tables in the database to the
     * current version, creating them if necessary.
     *
     * @param db Database
     */
    private static void updateDatabase(Context context, SQLiteDatabase db, int fromVersion,
            int toVersion) {

        iLog.d(TAG, String.format(Locale.US, "updateDatabase fromVersion[%d],  toVersion[%d])",
                fromVersion, toVersion));

        if (fromVersion > toVersion) {
            iLog.e(TAG, "Illegal update request: can't downgrade from " + fromVersion + " to " +
                    toVersion + ". Did you forget to wipe data?");
            throw new IllegalArgumentException();
        }

        if (fromVersion < 1) {
            // create audio_meta table
            // createAudioTable(db);
            createDLNATable(db);
        }

        if (fromVersion < 10001) {
            // Drop audio View for Store. From this verion, only use audio_meta
            // table.
            db.execSQL("DROP VIEW IF EXISTS audio");
            db.execSQL("DROP TABLE IF EXISTS album_art");
            db.execSQL("DROP VIEW IF EXISTS audio_with_albumart");
            db.execSQL("DROP VIEW IF EXISTS album_info");
            db.execSQL("DROP VIEW IF EXISTS artist_info");
            db.execSQL("DROP VIEW IF EXISTS music_folders_view");
            db.execSQL("DROP VIEW IF EXISTS searchhelpertitle");
            db.execSQL("DROP TABLE IF EXISTS audio_playlists");
            db.execSQL("DROP TABLE IF EXISTS audio_playlists_map");
            db.execSQL("DROP TABLE IF EXISTS audio_playlists_map_cache");
            db.execSQL("DROP TABLE IF EXISTS download_queue");
            db.execSQL("DROP TABLE IF EXISTS dlna_dms_contents_table");
            db.execSQL("DROP TABLE IF EXISTS inventory");
            db.execSQL("DROP TABLE IF EXISTS remote_songs");
            db.execSQL("DROP VIEW IF EXISTS remote_songs_view");

            // for removing useless column
            // db.execSQL("CREATE TABLE IF NOT EXISTS audio_meta2 ("
            // + MusicDBInfo.AUDIO_TABLE_COLUMNS_DEFINITION_V1 + ");");
            // // copy data from old table
            // db.execSQL("INSERT OR REPLACE INTO audio_meta2 ("
            // + MusicDBInfo.AUDIO_TABLE_COLUMNS + ") SELECT "
            // + MusicDBInfo.AUDIO_TABLE_COLUMNS + " FROM audio_meta;");
            db.execSQL("DROP TABLE IF EXISTS audio_meta");
            // db.execSQL("ALTER TABLE audio_meta2 RENAME TO audio_meta;");
        }

        // 1st release's db version is 20061
        if (fromVersion < 20061) {
            // For base table
            createAudioTable(db);
            createPlaylistTable(db);

            createMusicDBInfoTable(db);

            // For Online
            createOnlineTable(db);

            // For CardView
            createMusicCacheMapTable(db);
        }

        if (fromVersion < 20062) {
            db.execSQL("AlTER TABLE " + MusicDBInfo.AUDIO_PLAYLIST_TABLE_NAME +
                    " ADD COLUMN server_id INTEGER;");
            db.execSQL("AlTER TABLE " + MusicDBInfo.AUDIO_PLAYLIST_TABLE_NAME +
                    " ADD COLUMN sync_state INTEGER;");
            db.execSQL("AlTER TABLE " + MusicDBInfo.AUDIO_PLAYLIST_TABLE_NAME +
                    " ADD COLUMN track_sync_state INTEGER;");
        }

        if (fromVersion < 20064) {
            // create audio_meta_helper table to sync local contents.
            db.execSQL("DROP TABLE IF EXISTS audio_meta_helper");
            db.execSQL("CREATE TABLE audio_meta_helper AS SELECT * FROM audio_meta WHERE _id < 1");
        }

        if (fromVersion < 20065) {
            db.execSQL("DROP TABLE IF EXISTS audio_meta_helper");
        }

        if (fromVersion < 20066) {
            db.execSQL("DROP TABLE IF EXISTS " + OnlineTracks.MAP_TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineTracks.MAP_TABLE_NAME + " (" +
                    OnlineTracks.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20067) {
            db.execSQL("DROP TABLE IF EXISTS " + OnlineBanner.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineBanner.TABLE_NAME + " (" +
                    OnlineBanner.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20068) {
            createMusicDBInfoTable(db);
        }

        if (fromVersion < 20069) {
            // recreate online topic
            db.execSQL("DROP TABLE IF EXISTS " + OnlineTopics.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineTopics.TABLE_NAME + " (" +
                    OnlineTopics.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20070) {
            db.execSQL("DROP TABLE IF EXISTS " + OnlineBanner.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineBanner.TABLE_NAME + " (" +
                    OnlineBanner.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20071) {
            createMusicDBInfoTable(db);
            db.execSQL("INSERT INTO " + MusicDBInfo.DBSyncInfo.TABLE_NAME + " values('" +
                    MusicDBInfo.DBSyncInfo.CP_MEDIA_PROVIDER + "', '" +
                    String.valueOf(System.currentTimeMillis()) + "', '" +
                    new SimpleDateFormat("MM-dd hh:mm:ss.SSS").format(new Date()).toString() +
                    "', '0', '', '" + Locale.getDefault().toString() + "');");
        }

        if (fromVersion < 20072) {
            db.execSQL("DROP TABLE IF EXISTS " + OnlineRank.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineRank.TABLE_NAME + " (" +
                    OnlineRank.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20073) {
            createRadioCategory(db);
        }

        if (fromVersion < 20074) {
            createDbIndex(db);
        }

        if (fromVersion < 20075) {
            db.execSQL("DELETE FROM smusic_db_info WHERE " +
                    "sync_content_type = 'online_ultimate_radio_category';");
            db.execSQL("DROP TABLE IF EXISTS " + OnlineRadioCategory.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineRadioCategory.TABLE_NAME + " (" +
                    OnlineRadioCategory.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20076) {
            if (AppFeatures.REGIONAL_CHN_PINYIN_ENABLED) {
                try {
                    db.execSQL("ALTER TABLE audio_meta ADD COLUMN title_pinyin TEXT;");
                    db.execSQL(
                            "ALTER TABLE audio_meta ADD COLUMN genre_name_pinyin TEXT default '<unknown>';");
                    db.execSQL(
                            "ALTER TABLE audio_meta ADD COLUMN composer_pinyin TEXT default '<unknown>';");
                    db.execSQL("ALTER TABLE audio_meta ADD COLUMN _display_name_pinyin TEXT;");
                    db.execSQL(
                            "ALTER TABLE audio_meta ADD COLUMN bucket_display_name_pinyin TEXT;");

                    db.execSQL(
                            "ALTER TABLE audio_meta ADD COLUMN artist_pinyin TEXT default '<unknown>';");
                    db.execSQL(
                            "ALTER TABLE audio_meta ADD COLUMN album_pinyin TEXT default '<unknown>';");

                    db.execSQL("ALTER TABLE audio_meta ADD COLUMN artist_search_key TEXT;");
                    db.execSQL("ALTER TABLE audio_meta ADD COLUMN album_search_key TEXT;");
                    db.execSQL("ALTER TABLE audio_meta ADD COLUMN title_search_key TEXT;");

                    db.execSQL("ALTER TABLE audio_playlists ADD COLUMN name_pinyin TEXT;");
                } catch (SQLiteException e) {
                    iLog.e(TAG, "duplicate column :" + e.toString());
                }

                db.execSQL("UPDATE audio_meta SET date_modified = 0 WHERE content_location = 1;");
            }
        }

        if (fromVersion < 20078) {
            // constraint is changed - artist_id -> (artist_id, artist_category_id)
            db.execSQL("DROP TABLE IF EXISTS " + OnlineArtists.TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineArtists.TABLE_NAME + " (" +
                    OnlineArtists.SCHEMA_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20079) {
            // For local view

            createArtistMapView(db);

            createSearchHelperTitleView(db);
        }

        if (fromVersion < 20080) {
            db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.AUDIO_PLAYLISTS_MAP_CACHE_TABLE_NAME);
            db.execSQL("CREATE TABLE IF NOT EXISTS " +
                    MusicDBInfo.AUDIO_PLAYLISTS_MAP_CACHE_TABLE_NAME + " (" +
                    MusicDBInfo.PLAYLIST_MAP_CACHE_TABLE_COLUMNS_DEFINITION + ");");
        }

        if (fromVersion < 20081) {
            createOnlineFmCategory(db);
        }

        if (fromVersion < 20083) {
            recreateTableWithCpAttrsColumn(db);

            createAlbumInfoView(db);
            createArtistInfoView(db);
            createGenresInfoView(db);
            createFolderInfoView(db);
            createComposerInfoView(db);
            createSearchView(db);
        }

        if (fromVersion < 20084) {
            db.execSQL("update audio_meta SET date_modified = 0");

            // @formatter:off
            // Cleans up when an audio file is deleted
            db.execSQL("CREATE TRIGGER IF NOT EXISTS audio_meta_cleanup DELETE ON audio_meta "
                + "BEGIN "
                + "  DELETE FROM audio_playlists_map WHERE audio_id = old._id;"
                + "END");

            // for categorized tracks trigger.
            // Cleans up when an audio file is deleted
            db.execSQL("CREATE TRIGGER IF NOT EXISTS audio_meta_categorized_tracks_map_trigger DELETE ON audio_meta "
                + "BEGIN "
                + "  DELETE FROM " + OnlineTracks.MAP_TABLE_NAME
                + " WHERE audio_id = old._id;"
                + "END");
            // @formatter:on
        }

        if (fromVersion < 20085) {
            db.execSQL(
                    "DELETE FROM audio_playlists_map WHERE audio_id NOT IN (SELECT _id FROM audio_meta)");
        }

        if (fromVersion < 20086) {
            db.execSQL("DROP TABLE IF EXISTS online_cache_tracks");
        }

        if (fromVersion < 20087) {
            createDownloadTable(db);
        }

        if (fromVersion < 20088) {
            db.execSQL("AlTER TABLE " + MusicDBInfo.AUDIO_TABLE_NAME +
                    " ADD COLUMN drm_type INTEGER;");
        }

        if (fromVersion < 20089) {
            // streaming cache table has been move to external streaming cache db.
            db.execSQL("DROP TABLE IF EXISTS streaming_cache_table");
        }

        if (fromVersion < 20090) {
            MusicSyncService.sync(context, MusicSyncService.EVENT_SYNC_DOWNLOADED);
        }

        if (fromVersion < 20091) {
            createAlbumInfoView(db);
            createSearchView(db);
        }
    }

    private static void createPlaylistTable(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.AUDIO_PLAYLIST_TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.AUDIO_PLAYLISTS_MAP_TABLE_NAME);

        // Contains audio playlist definitions
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.AUDIO_PLAYLIST_TABLE_NAME + " (" +
                MusicDBInfo.PLAYLIST_TABLE_COLUMNS_DEFINITION + ");");

        // Contains mappings between audio playlists and audio files
        db.execSQL(
                "CREATE TABLE IF NOT EXISTS " + MusicDBInfo.AUDIO_PLAYLISTS_MAP_TABLE_NAME + " (" +
                        MusicDBInfo.PLAYLIST_MAP_TABLE_COLUMNS_DEFINITION + ");");

        // @formatter:off
        // Cleans up when an audio playlist is deleted
        db.execSQL("CREATE TRIGGER IF NOT EXISTS audio_playlists_cleanup DELETE ON audio_playlists "
                + "BEGIN "
                + "  DELETE FROM audio_playlists_map WHERE playlist_id = old._id;"
                + "  SELECT _DELETE_FILE(old._data);"
                + "END");

        // Cleans up when an audio file is deleted
        db.execSQL("CREATE TRIGGER IF NOT EXISTS audio_meta_cleanup DELETE ON audio_meta "
                + "BEGIN "
                + "  DELETE FROM audio_playlists_map WHERE audio_id = old._id;"
                + "END");
        // @formatter:on
    }

    private static void createMusicCacheMapTable(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.MusicCacheMap.MAP_TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.MusicCacheMap.MAP_TABLE_NAME + " (" +
                MusicDBInfo.MusicCacheMap.SCHEMA_COLUMNS_DEFINITION_V1 + ");");
    }

    private static void createDLNATable(SQLiteDatabase db) {
        // create all share table
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.DLNA_TABLE_NAME);
        db.execSQL("CREATE TABLE " + MusicDBInfo.DLNA_TABLE_NAME + " (" +
                MusicDBInfo.DLNA_TABLE_COLUMNS_DEFINITION + ");");
        // create all share open intent table
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.DLNA_OPEN_INTENT_CONTENTS_TABLE_NAME);
        db.execSQL("CREATE TABLE " + MusicDBInfo.DLNA_OPEN_INTENT_CONTENTS_TABLE_NAME + " (" +
                MusicDBInfo.DLNA_TABLE_COLUMNS_DEFINITION + ");");
        // create all share provider table
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.DLNA_PROVIDER_TABLE_NAME);
        db.execSQL("CREATE TABLE " + MusicDBInfo.DLNA_PROVIDER_TABLE_NAME + " (" +
                MusicDBInfo.DLNA_PROVIDER_TABLE_COLUMNS_DEFINITION + ");");
        // create all share avplayer table
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.DLNA_AVPLAYER_TABLE_NAME);
        db.execSQL("CREATE TABLE " + MusicDBInfo.DLNA_AVPLAYER_TABLE_NAME + " (" +
                MusicDBInfo.DLNA_AVPLAYER_TABLE_COLUMNS_DEFINITION + ");");

        // album art Table for DLNA
        db.execSQL("DROP TABLE IF EXISTS dlna_album_art");
        db.execSQL("CREATE TABLE IF NOT EXISTS dlna_album_art (" + "album_id INTEGER PRIMARY KEY," +
                "album_art TEXT" + ");");
    }

    static final String SEC_PLAYLIST_COLUMNS_ADDED = ",mini_thumb_data";

    private static void createAudioTable(SQLiteDatabase db) {
        iLog.d(TAG, "createAudioTable");

        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.AUDIO_TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.AUDIO_TABLE_NAME + " (" +
                MusicDBInfo.AUDIO_TABLE_COLUMNS_DEFINITION_V1 + ");");

        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.AUDIO_VIEW_NAME);
        db.execSQL("CREATE VIEW " + MusicDBInfo.AUDIO_VIEW_NAME + " AS SELECT * FROM " +
                MusicDBInfo.AUDIO_TABLE_NAME);
    }

    private static void createMusicDBInfoTable(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.DBSyncInfo.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.DBSyncInfo.TABLE_NAME + " (" +
                MusicDBInfo.DBSyncInfo.SCHEMA_COLUMNS_DEFINITION + ");");
    }

    private static void createAlbumInfoView(SQLiteDatabase db) {
        iLog.d(TAG, "createAlbumInfoView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.ALBUM_INFO_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.ALBUM_INFO_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_ALBUM_INFO_QUERY);
    }

    private static void createArtistInfoView(SQLiteDatabase db) {
        iLog.d(TAG, "createArtistInfoView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.ARTIST_INFO_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.ARTIST_INFO_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_ARTIST_INFO_QUERY);
    }

    private static void createArtistMapView(SQLiteDatabase db) {
        iLog.d(TAG, "createArtistMapView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.ARTIST_ALBUM_MAP_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.ARTIST_ALBUM_MAP_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_ARTIST_ALBUM_MAP_QUERY);
    }

    private static void createComposerInfoView(SQLiteDatabase db) {
        iLog.d(TAG, "createComposerInfoView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.COMPOSER_INFO_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.COMPOSER_INFO_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_COMPOSER_INFO_QUERY);
    }

    private static void createFolderInfoView(SQLiteDatabase db) {
        iLog.d(TAG, "createFolderInfoView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.FOLDER_INFO_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.FOLDER_INFO_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_FOLDER_INFO_QUERY);
    }

    private static void createGenresInfoView(SQLiteDatabase db) {
        iLog.d(TAG, "createFolderInfoView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.GENRES_INFO_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.GENRES_INFO_VIEW_NAME + " AS " +
                MusicDBInfo.VIEW_GENRE_INFO_QUERY);
    }

    private static void createSearchHelperTitleView(SQLiteDatabase db) {
        iLog.d(TAG, "createSearchHelperTitleView");
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.SEARCH_HELPER_TITLE_VIEW_NAME);
        db.execSQL(
                "CREATE VIEW IF NOT EXISTS " + MusicDBInfo.SEARCH_HELPER_TITLE_VIEW_NAME + " AS " +
                        MusicDBInfo.VIEW_SEARCH_HELPER_TITLE_QUERY);
    }

    private static void createSearchView(SQLiteDatabase db) {
        iLog.d(TAG, "createSearchView");

        // artist, album, title integrated search view
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.SEARCH_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.SEARCH_VIEW_NAME + " AS " +
                MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_ARTIST
                // Local Album union
                + " UNION ALL " + MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_ALBUM
                // Local Title union
                + " UNION ALL " + MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_TRACK);

        // artist search view
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.SEARCH_ALBUM_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.SEARCH_ALBUM_VIEW_NAME + " AS " +
                MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_ALBUM);

        // album search view
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.SEARCH_ARTIST_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.SEARCH_ARTIST_VIEW_NAME + " AS " +
                MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_ARTIST);

        // track search view
        db.execSQL("DROP VIEW IF EXISTS " + MusicDBInfo.SEARCH_TRACK_VIEW_NAME);
        db.execSQL("CREATE VIEW IF NOT EXISTS " + MusicDBInfo.SEARCH_TRACK_VIEW_NAME + " AS " +
                MusicDBInfo.LOCAL_VIEW_SEARCH_QUERY_TRACK);
    }

    private static void createOnlineTable(SQLiteDatabase db) {
        iLog.d("TAG", "createOnlineTable");
        // for categorized tracks
        db.execSQL("DROP TABLE IF EXISTS " + OnlineTracks.MAP_TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineTracks.MAP_TABLE_NAME + " (" +
                OnlineTracks.SCHEMA_COLUMNS_DEFINITION + ");");

        // for categorized tracks trigger.
        // Cleans up when an audio file is deleted
        db.execSQL("DROP TRIGGER IF EXISTS audio_meta_categorized_tracks_map_trigger;");
        db.execSQL(
                "CREATE TRIGGER IF NOT EXISTS audio_meta_categorized_tracks_map_trigger DELETE ON audio_meta " +
                        "BEGIN DELETE FROM " + OnlineTracks.MAP_TABLE_NAME +
                        " WHERE audio_id = old._id; END");

        // online artist
        db.execSQL("DROP TABLE IF EXISTS " + OnlineArtists.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineArtists.TABLE_NAME + " (" +
                OnlineArtists.SCHEMA_COLUMNS_DEFINITION + ");");

        // online album
        db.execSQL("DROP TABLE IF EXISTS " + OnlineAlbums.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineAlbums.TABLE_NAME + " (" +
                OnlineAlbums.SCHEMA_COLUMNS_DEFINITION + ");");

        // online topic
        db.execSQL("DROP TABLE IF EXISTS " + OnlineTopics.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineTopics.TABLE_NAME + " (" +
                OnlineTopics.SCHEMA_COLUMNS_DEFINITION + ");");
    }

    /**
     * Before create table, drop table
     */
    private static void createTableInternal(SQLiteDatabase db, String tableName,
            String tableDefinition) {
        db.execSQL("DROP TABLE IF EXISTS " + tableName);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + tableName + " (" + tableDefinition + ");");
    }

    private static void createRadioCategory(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + OnlineRadioCategory.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineRadioCategory.TABLE_NAME + " (" +
                OnlineRadioCategory.SCHEMA_COLUMNS_DEFINITION + ");");
    }

    private static void createOnlineFmCategory(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + OnlineFmCategory.TABLE_NAME);
        db.execSQL("DROP TABLE IF EXISTS " + OnlineFmRecently.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineFmCategory.TABLE_NAME + " (" +
                OnlineFmCategory.SCHEMA_COLUMNS_DEFINITION + ");");
        db.execSQL("CREATE TABLE IF NOT EXISTS " + OnlineFmRecently.TABLE_NAME + " (" +
                OnlineFmRecently.SCHEMA_COLUMNS_DEFINITION + ");");
    }

    private static void createDownloadTable(SQLiteDatabase db) {
        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.Download.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.Download.TABLE_NAME + " (" +
                MusicDBInfo.Download.TABLE_COLUMNS_DEFINITION + ");");

        db.execSQL("DROP TABLE IF EXISTS " + MusicDBInfo.Download.Tracks.TABLE_NAME);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + MusicDBInfo.Download.Tracks.TABLE_NAME + " (" +
                MusicDBInfo.Download.Tracks.TABLE_COLUMNS_DEFINITION + ");");

        db.execSQL(
                "DROP TRIGGER IF EXISTS " + MusicDBInfo.Download.Trigger.DOWNLOAD_COMPLETE_TRIGGER);
        db.execSQL("CREATE TRIGGER IF NOT EXISTS " +
                MusicDBInfo.Download.Trigger.DOWNLOAD_COMPLETE_TRIGGER + " " +
                MusicDBInfo.Download.Trigger.DOWNLOAD_COMPLETE_SCHEMA);
    }

    private static void createDbIndex(SQLiteDatabase db) {
        db.execSQL("CREATE INDEX genre_name_index ON audio_meta(genre_name);");
        db.execSQL("CREATE INDEX composer_index ON audio_meta(composer);");
        db.execSQL("CREATE INDEX bucket_id_index ON audio_meta(bucket_id);");
    }

    private static void recreateTableWithCpAttrsColumn(SQLiteDatabase db) {
        //@formatter:off
        recreateTableWithCpAttrsColumn(db, MusicDBInfo.AUDIO_TABLE_NAME, MusicDBInfo.AUDIO_TABLE_COLUMNS_DEFINITION_V2, RESERVED_COLUMNS_AUDIO_META, "content_location", "cp_attrs");
        recreateTableWithCpAttrsColumn(db, MusicDBInfo.MusicCacheMap.MAP_TABLE_NAME, MusicDBInfo.MusicCacheMap.SCHEMA_COLUMNS_DEFINITION_V2, RESERVED_COLUMNS_MUSIC_CACHE_MAP, "content_location", "cp_attrs");
        //@formatter:on
    }

    private static void recreateTableWithCpAttrsColumn(SQLiteDatabase db, String tableName,
            String columnsDefinition, String reservedColumns, String oldColumnName,
            String newColumnName) {
        //@formatter:off
        String tempTable = tableName + "_temp";

        db.execSQL("DROP TABLE IF EXISTS " + tempTable);
        db.execSQL("CREATE TABLE IF NOT EXISTS " + tempTable + " (" + columnsDefinition + ");");

        db.execSQL("INSERT INTO " + tempTable + " (" + reservedColumns + ", " + newColumnName + ") " +
                "SELECT " + reservedColumns + "," +
                " CASE WHEN " + oldColumnName + " = 1 THEN " + CpAttrs.LOCAL +
                " WHEN " + oldColumnName + " = 2 THEN " + CpAttrs.ULTIMATE +
                " WHEN " + oldColumnName + " = 0 THEN " + CpAttrs.LOCAL +
                " WHEN " + oldColumnName + " = 4 THEN " + CpAttrs.DLNA + " END " +
                "FROM " + tableName);
        db.execSQL("DROP TABLE " + tableName);
        db.execSQL("ALTER TABLE " + tempTable + " RENAME TO " + tableName);
        //@formatter:on
    }

    private static final String RESERVED_COLUMNS_AUDIO_META =
            "_id, source_id, _data, _size, mime_type, title, title_key, _display_name, duration, " +
                    "track, artist_id, artist, artist_key, album_id, album, album_key, album_art, " +
                    "album_artist, genre_name, composer, year, year_name, bucket_id, " +
                    "bucket_display_name, sampling_rate, bit_depth, is_music, is_favorite, " +
                    "is_secretbox, date_added, date_modified, date_updated, recently_played, " +
                    "most_played, provider_id, provider_name, extension, seed, media_type, " +
                    "is_downloaded, exclusivity";

    private static final String RESERVED_COLUMNS_MUSIC_CACHE_MAP =
            "_id, category, keyword, title, album_id, played_count, date_added, number_of_tracks, total_duration";
}

八、数据库的加密

开发中对于存储于数据库中的敏感数据,我们可以通过对数据库加密来进行保护。GreenDao可以通过SQLCipher来进行加密处理。

//build.gradle(module)
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.0"
    defaultConfig {
        applicationId "com.example.sourcecodetest"
        minSdkVersion 19
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

    implementation 'org.greenrobot:greendao:3.2.2' // add library
    implementation 'net.zetetic:android-database-sqlcipher:3.5.6' // add sqlcipher library
}

greendao {
    schemaVersion 7 //数据库版本号
    daoPackage 'com.example.sourcecodetest.database'
    //设置DaoMaster、DaoSession、Dao包名
    targetGenDir 'src/main/java' //设置DaoMaster、DaoSession、Dao目录,请注意,这里路径用 / 不要用 .
    generateTests false //设置为true以自动生成单元测试
    targetGenDirTests 'src/main/java' //应存储生成的单元测试的基本目录。默认为src/androidTest/java
}

//MyApplication
public class MyApplication extends Application {
    private static final String TAG = "MyApplication";
    private DaoSession daoSession;

    @Override
    public void onCreate() {
        super.onCreate();
        Log.d(TAG, "zwm, onCreate");
        initGreenDao();
    }

    /**
     * 初始化GreenDao,直接在Application中进行初始化操作
     */
    private void initGreenDao() {
        Log.d(TAG, "zwm, initGreenDao");
        //MyDaoMaster helper = new MyDaoMaster(this, "tomorrow.db"); //自定义DaoMaster.OpenHelper,用于处理数据库升级
        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "tomorrow.db");
        //SQLiteDatabase db = helper.getWritableDatabase(); //不加密的写法
        Database db = helper.getEncryptedWritableDb("zwm"); //数据库加密密码为“zwm"的写法
        DaoMaster daoMaster = new DaoMaster(db);
        daoSession = daoMaster.newSession();
    }

    public DaoSession getDaoSession() {
        return daoSession;
    }
}

//MainActivity
public class MainActivity extends AppCompatActivity {
    private static final String TAG = "MainActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Log.d(TAG, "zwm, onCreate");

        insert(); //插入数据后注释掉,用于测试数据库升级
        List<Student> list = loadStudents();
        for(Student student : list) {
            Log.d(TAG, "zwm, student NO." + student.getStudentNo() + ", _id: " + student.getId() + ", age: " + student.getAge() + ", name: " + student.getName());
            Log.d(TAG, "zwm, student newField: " + student.getAddNewField());
            List<Teacher> teacherList = student.getTeacherList();
            Log.d(TAG, "zwm, teacherList.size: " + teacherList.size());
            if(teacherList != null && teacherList.size() > 0) {
                for(Teacher teacher : teacherList) {
                    Log.d(TAG, "zwm, teacher NO." + teacher.getTeacherNo() + ", _id: " + teacher.getId() + ", age: " + teacher.getAge() + ", name: " + teacher.getName());
                }
            }
        }

        List<Teacher> list2 = loadTeachers();
        for(Teacher teacher : list2) {
            Log.d(TAG, "zwm, teacher NO." + teacher.getTeacherNo() + ", _id: " + teacher.getId() + ", age: " + teacher.getAge() + ", name: " + teacher.getName());
            List<Student> studentList = teacher.getStudentList();
            Log.d(TAG, "zwm, studentList.size: " + studentList.size());
            if(studentList != null && studentList.size() > 0) {
                for(Student student : studentList) {
                    Log.d(TAG, "zwm, student NO." + student.getStudentNo() + ", _id: " + student.getId() + ", age: " + student.getAge() + ", name: " + student.getName());
                }
            }
        }
    }

    public void insert() {
        Log.d(TAG, "zwm, insert");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        Student student = new Student();
        student.setStudentNo(5551);
        student.setAge(18);
        student.setTelPhone("5524307");
        student.setName("学生1");
        student.setSex("男");
        student.setAddress("广州");
        student.setGrade("一");
        student.setSchoolName("大学");
        daoSession.insert(student);

        Student student2 = new Student();
        student2.setStudentNo(5552);
        student2.setAge(19);
        student2.setTelPhone("5524308");
        student2.setName("学生2");
        student2.setSex("男");
        student2.setAddress("深圳");
        student2.setGrade("二");
        student2.setSchoolName("大学");
        daoSession.insert(student2);

        Student student3 = new Student();
        student3.setStudentNo(5553);
        student3.setAge(20);
        student3.setTelPhone("5524309");
        student3.setName("学生3");
        student3.setSex("男");
        student3.setAddress("北京");
        student3.setGrade("三");
        student3.setSchoolName("大学");
        daoSession.insert(student3);

        Teacher teacher1 = new Teacher();
        teacher1.setTeacherNo(9991);
        teacher1.setAge(28);
        teacher1.setTelPhone("9924307");
        teacher1.setName("教师1");
        teacher1.setSex("男");
        teacher1.setSubject("语文");
        teacher1.setSchoolName("大学");
        daoSession.insert(teacher1);

        Teacher teacher2 = new Teacher();
        teacher2.setTeacherNo(9992);
        teacher2.setAge(29);
        teacher2.setTelPhone("9924308");
        teacher2.setName("教师2");
        teacher2.setSex("男");
        teacher2.setSubject("数学");
        teacher2.setSchoolName("大学");
        daoSession.insert(teacher2);

        Teacher teacher3 = new Teacher();
        teacher3.setTeacherNo(9993);
        teacher3.setAge(30);
        teacher3.setTelPhone("9924309");
        teacher3.setName("教师3");
        teacher3.setSex("男");
        teacher3.setSubject("英语");
        teacher3.setSchoolName("大学");
        daoSession.insert(teacher3);

        StudentAndTeacherBean studentAndTeacher = new StudentAndTeacherBean();
        studentAndTeacher.setStudentId(Long.valueOf(1));
        studentAndTeacher.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher);

        StudentAndTeacherBean studentAndTeacher2 = new StudentAndTeacherBean();
        studentAndTeacher2.setStudentId(Long.valueOf(1));
        studentAndTeacher2.setTeacherId(Long.valueOf(2));
        daoSession.insert(studentAndTeacher2);

        StudentAndTeacherBean studentAndTeacher3 = new StudentAndTeacherBean();
        studentAndTeacher3.setStudentId(Long.valueOf(2));
        studentAndTeacher3.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher3);

        StudentAndTeacherBean studentAndTeacher4 = new StudentAndTeacherBean();
        studentAndTeacher4.setStudentId(Long.valueOf(2));
        studentAndTeacher4.setTeacherId(Long.valueOf(3));
        daoSession.insert(studentAndTeacher4);

        StudentAndTeacherBean studentAndTeacher5 = new StudentAndTeacherBean();
        studentAndTeacher5.setStudentId(Long.valueOf(3));
        studentAndTeacher5.setTeacherId(Long.valueOf(1));
        daoSession.insert(studentAndTeacher5);

        StudentAndTeacherBean studentAndTeacher6 = new StudentAndTeacherBean();
        studentAndTeacher6.setStudentId(Long.valueOf(3));
        studentAndTeacher6.setTeacherId(Long.valueOf(2));
        daoSession.insert(studentAndTeacher6);

        StudentAndTeacherBean studentAndTeacher7 = new StudentAndTeacherBean();
        studentAndTeacher7.setStudentId(Long.valueOf(3));
        studentAndTeacher7.setTeacherId(Long.valueOf(3));
        daoSession.insert(studentAndTeacher7);
    }

    public List<Student> loadStudents(){
        Log.d(TAG, "zwm, loadStudents");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        List<Student> students = daoSession.loadAll(Student.class);
        return students;
    }

    public List<Teacher> loadTeachers(){
        Log.d(TAG, "zwm, loadTeachers");
        DaoSession daoSession = ((MyApplication) getApplication()).getDaoSession();
        List<Teacher> teachers = daoSession.loadAll(Teacher.class);
        return teachers;
    }
}

//输出log
2020-01-08 20:23:43.476 3853-3853/com.example.sourcecodetest D/MyApplication: zwm, onCreate
2020-01-08 20:23:43.476 3853-3853/com.example.sourcecodetest D/MyApplication: zwm, initGreenDao
2020-01-08 20:23:44.113 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, onCreate
2020-01-08 20:23:44.113 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, insert
2020-01-08 20:23:44.357 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, loadStudents
2020-01-08 20:23:44.361 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 20:23:44.361 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 20:23:44.369 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 20:23:44.369 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 20:23:44.370 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 20:23:44.370 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 20:23:44.370 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 20:23:44.376 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 2
2020-01-08 20:23:44.376 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 20:23:44.376 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 20:23:44.377 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 20:23:44.377 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student newField: false
2020-01-08 20:23:44.380 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacherList.size: 3
2020-01-08 20:23:44.380 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 20:23:44.380 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 20:23:44.380 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 20:23:44.380 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, loadTeachers
2020-01-08 20:23:44.384 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9991, _id: 1, age: 28, name: 教师1
2020-01-08 20:23:44.389 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 3
2020-01-08 20:23:44.389 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 20:23:44.389 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 20:23:44.390 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 20:23:44.390 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9992, _id: 2, age: 29, name: 教师2
2020-01-08 20:23:44.393 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 20:23:44.394 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5551, _id: 1, age: 18, name: 学生1
2020-01-08 20:23:44.394 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3
2020-01-08 20:23:44.394 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, teacher NO.9993, _id: 3, age: 30, name: 教师3
2020-01-08 20:23:44.396 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, studentList.size: 2
2020-01-08 20:23:44.396 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5552, _id: 2, age: 19, name: 学生2
2020-01-08 20:23:44.397 3853-3853/com.example.sourcecodetest D/MainActivity: zwm, student NO.5553, _id: 3, age: 20, name: 学生3

//数据库文件
取出数据库文件(tomorrow.db)到电脑本地,无法通过SQLite Expert Professional软件打开,提示数据库文件已经加密了。

九、源码解析

GreenDao源码解析

上一篇下一篇

猜你喜欢

热点阅读