Android greenDAO数据库配置教程

来源:互联网 发布:锡林浩特网络宾馆 编辑:程序博客网 时间:2024/04/29 23:34

一、环境配置

1、在Android Studio中,在.src/main目录下新建一个java-gen文件夹,和java文件夹同级。用于存放greenDAO生成的DaoMaster、DaoSession、Table、TableDaoSession实体类。



2、配置项目的app.gradle文件,指定java-gen文件,引入greenDAO第三方jar包


sourceSets {        main {            java.srcDirs = ['src/main/java', 'src/main/java-gen']        }    }
compile 'de.greenrobot:greendao:1.3.7'

3、新建一个greengenerator模块,用于代码自动生成DaoMaster、DaoSession、Table、TableDao实体类




配置新建moudle的build.gradle文件


compile 'de.greenrobot:greendao-generator:1.3.1'


至此,greenDAO的环境配置就完成了。


二、利用greedgenerater模块生成DaoMaster、DaoSession、Table、TableDao实体类的代码,编写moudle下的MyClass类

import de.greenrobot.daogenerator.DaoGenerator;import de.greenrobot.daogenerator.Entity;import de.greenrobot.daogenerator.Schema;public class MyClass {    public static void main(String[] args) throws Exception {        // 正如你所见的,你创建了一个用于添加实体(Entity)的模式(Schema)对象。        // 两个参数分别代表:数据库版本号与自动生成代码的包路径。        Schema schema = new Schema(1, "test.greendao");//      当然,如果你愿意,你也可以分别指定生成的 Bean 与 DAO 类所在的目录,只要如下所示://      Schema schema = new Schema(1, "test.greendao.bean");//      schema.setDefaultJavaPackageDao("test.greendao.dao");        // 模式(Schema)同时也拥有两个默认的 flags,分别用来标示 entity 是否是 activie 以及是否使用 keep sections。        // schema2.enableActiveEntitiesByDefault();        // schema2.enableKeepSectionsByDefault();        // 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。        addNote(schema);        // 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。        // 其实,输出目录的路径可以在 build.gradle 中设置,有兴趣的朋友可以自行搜索,这里就不再详解。        new DaoGenerator().generateAll(schema, "/Users/licheng/Documents/Healthdoctor/app/src/main/java-gen");    }    /**     * @param schema     */    private static void addNote(Schema schema) {        // 一个实体(类)就关联到数据库中的一张表,此处表名为「Note」(既类名)        Entity note = schema.addEntity("TestTable");        // 你也可以重新给表命名        // note.setTableName("NODE");        // greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值        // 接下来你便可以设置表中的字段:        note.addIdProperty();        note.addStringProperty("aa");        // 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。        // For example, a property called “creationDate” will become a database column “CREATION_DATE”.        note.addIntProperty("bb");        note.addIntProperty("cc");        note.addIntProperty("dd");        note.addIntProperty("ee");    }}

如果运行结果打印如下,说明配置成功并且实体类生成成功



三、greenDAO代码全局配置

1、DaoMaster、DaoSession配置

一个APP项目,一般不只一个数据库,一个数据库里也不只一个表,如果有多个表的情况,按照上面的配置,会发现每生成一个实体类表,除了Table和TableDao类外,都会有一个DaoMaster和DaoSession生成,这时候我们就可以配置DaoMaster和DaoSession类了,一个类管理多张表。

我们可以再生成一个实体类表,表名为TestAnOtherTable,这样,一个数据库下就有了2个表。


配置DaoMaster类

package test.greendao;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.database.sqlite.SQLiteOpenHelper;import android.util.Log;import de.greenrobot.dao.AbstractDaoMaster;import de.greenrobot.dao.identityscope.IdentityScopeType;import test.greendao.TestAnOtherTableDao;// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT./**  * Master of DAO (schema version 1): knows all DAOs.*/public class DaoMaster extends AbstractDaoMaster {    public static final int SCHEMA_VERSION = 1;    /** Creates underlying database table using DAOs. */    public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {        TestAnOtherTableDao.createTable(db, ifNotExists);        TestTableDao.createTable(db, ifNotExists);    }        /** Drops underlying database table using DAOs. */    public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {        TestAnOtherTableDao.dropTable(db, ifExists);        TestTableDao.dropTable(db, ifExists);    }        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);            createAllTables(db, false);        }    }        /** WARNING: Drops all table on Upgrade! Use only during development. */    public static class DevOpenHelper extends OpenHelper {        public DevOpenHelper(Context context, String name, CursorFactory factory) {            super(context, name, factory);        }        @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);        }    }    public DaoMaster(SQLiteDatabase db) {        super(db, SCHEMA_VERSION);        registerDaoClass(TestAnOtherTableDao.class);        registerDaoClass(TestTableDao.class);    }        public DaoSession newSession() {        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);    }        public DaoSession newSession(IdentityScopeType type) {        return new DaoSession(db, type, daoConfigMap);    }    }
配置DaoSession类

package test.greendao;import android.database.sqlite.SQLiteDatabase;import java.util.Map;import de.greenrobot.dao.AbstractDao;import de.greenrobot.dao.AbstractDaoSession;import de.greenrobot.dao.identityscope.IdentityScopeType;import de.greenrobot.dao.internal.DaoConfig;import test.greendao.TestAnOtherTable;import test.greendao.TestAnOtherTableDao;// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT./** * {@inheritDoc} *  * @see de.greenrobot.dao.AbstractDaoSession */public class DaoSession extends AbstractDaoSession {    private final DaoConfig testAnOtherTableDaoConfig;    private final DaoConfig testTableDaoConfig;    private final TestAnOtherTableDao testAnOtherTableDao;    private final TestTableDao testTableDao;    public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>            daoConfigMap) {        super(db);        testAnOtherTableDaoConfig = daoConfigMap.get(TestAnOtherTableDao.class).clone();        testAnOtherTableDaoConfig.initIdentityScope(type);                testTableDaoConfig = daoConfigMap.get(TestTable.class).clone();        testTableDaoConfig.initIdentityScope(type);        testAnOtherTableDao = new TestAnOtherTableDao(testAnOtherTableDaoConfig, this);        testTableDao = new TestTableDao(testTableDaoConfig, this);        registerDao(TestAnOtherTable.class, testAnOtherTableDao);        registerDao(TestTable.class, testTableDao);    }        public void clear() {        testAnOtherTableDaoConfig.getIdentityScope().clear();        testTableDaoConfig.getIdentityScope().clear();    }    public TestAnOtherTableDao getTestAnOtherTableDao() {        return testAnOtherTableDao;    }    public TestTableDao getTestTableDao() {        return testTableDao;    }}

这样,2个表就可以通过一个DaoMaster和DaoSession管理了。


2、greenDAO Application配置

greedDAO官方建议,DaoSession最好配置在Application里。

我们新建一个GreenDaoUtils类,用来新建数据库以及管理所有数据库表。

public class GreenDaoUtils {    /**     * 创建数据库连接     *     * @param context     * @return     */    public static DaoSession createDB(Context context) {        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context,                TableNameEntity.DB_NAME, null);        return new DaoMaster(helper.getWritableDatabase()).newSession();    }      /**     * 给TestTable表插入数据     * @param testTable     * @param daoSession     */    public static void addTestTableInfo(TestTable testTable, DaoSession daoSession){        daoSession.getTestTableDao().insert(testTable);    }    /**     * 获取TestTable表所有数据     * @param daoSession     * @return     */    public static List<?> getTestTableInfoList(DaoSession daoSession){        QueryBuilder<TestTable> queryBuilder = daoSession.getTestTableDao()                .queryBuilder().orderAsc(TestTableDao.Properties.Id);        if(!ListUtils.isEmpty(queryBuilder.list())){            return queryBuilder.list();        }        return null;    }}

public class HealthApplication extends Application {    private GreenDaoUtils mGreenDaoUtils;    private DaoSession mDaoSession;    private static HealthApplication instance;    public static HealthApplication getInstance(){        return instance;    }    @Override    public void onCreate() {        super.onCreate();        instance = this;               //greenDao数据库        initGreenDao();    }    /** greenDao数据库框架初始化 **/    private void initGreenDao() {        mGreenDaoUtils = new GreenDaoUtils();        mDaoSession = mGreenDaoUtils.createDB(this);    }    public DaoSession getmDaoSession() {        return mDaoSession;    }   }

在代码中调用

DaoSession mDaoSession = HealthApplication.getInstance().getmDaoSession();        TestTable testTable = new TestTable();        testTable.setAa("aa");        testTable.setBb(11);        testTable.setCc(22);        testTable.setFf(44);        GreenDaoUtils.addTestTableInfo(testTable, mDaoSession);

这样,我们就通过上面代码向TestTable数据库表中插入了一条数据。关于greenDAO的sql语句语法,可以自行查找资料,这里就不再多述。


三、greedDAO数据库的升级

新建一个MigrationHelper类

import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import android.text.TextUtils;import android.util.Log;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import de.greenrobot.dao.AbstractDao;import de.greenrobot.dao.internal.DaoConfig;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(SQLiteDatabase db, Class<? extends AbstractDao<?, ?>>... daoClasses) {        generateTempTables(db, daoClasses);        DaoMaster.dropAllTables(db, true);        DaoMaster.createAllTables(db, false);        restoreData(db, daoClasses);    }    private void generateTempTables(SQLiteDatabase 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) {                    }                    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());        }    }    private void restoreData(SQLiteDatabase 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()));        throw exception;    }    private static List<String> getColumns(SQLiteDatabase 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;    }}


配置DaoMaster中的DevOpenHelper

/** WARNING: Drops all table on Upgrade! Use only during development. */    public static class DevOpenHelper extends OpenHelper {        public DevOpenHelper(Context context, String name, CursorFactory factory) {            super(context, name, factory);        }        @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, TestTable.class);            MigrationHelper.getInstance().migrate(db, TestAnOtherTable.class);        }    }

注意,onUpgrade方法,只有在数据库版本号更改后才会执行,数据库版本号在正式包环境中只能向上兼容,也就是版本号的值不能小于上个数据库的版本号。

public static final int SCHEMA_VERSION = 1;

每次改动数据库,该值需要更改。

如果数据库表字段有更新、或添加删除字段,或数据库有增删表,利用generater模块类重新生成实体类表,然后更改数据库版本号,就可以实现数据库的更新。


2 1
原创粉丝点击