GreenDAO系列之(1)入门

来源:互联网 发布:深圳阿里云幕布拍照 编辑:程序博客网 时间:2024/06/06 05:14

关于greenDao

简介

greenDAO 是一个开源的ORM数据库框架。它帮助开发者从日常的数据库的读写sql语句中解放出来,开发者只需要关注具体的Java对象,就能够进行数据库的访问操作。

image

greenDao features

1.强大的性能,可能是ORM数据库中性能最好的。官方把greenDao和OrmLite、ActiveAndroid做的性能对比,数据如下:
image
2. 易于使用的API
3. 低内存消耗
4. 包size比较小,如果不包含加密,大概proguard后的包size为8k。
5. 支持数据库加密: 支持SQLCipher。SQLCipher对个人开发者来说倒不错,不过对于公司来说吸引力不大。

greenDao 核心类说明

image

如上图所示,greenDao有几个核心类:
1. DaoMaster : db的管理类,是db的总入口,总管的角色,管理着database创建、更新以及数据库中有哪些表之类。每一个db对应一个DaoMaster。
2. DaoSession : 会话, 管理指定的schema的所有dao,另外DaoSession也支持数据缓存,可以指定dao是否使用缓存。
3. xxxDao : 某个table的操作对象
4. Entity : 通俗易懂,不解释了

greenDao工程说明

greenDao 的github包含两个公共组件 :
1. DaoCore :greenDao的核心框架,我们一般说的greenDao就是指这个
2. DaoGenerator :通俗易懂,就是xxxDao的生成器,帮助开发者生成xxxDAO对象,开发者只需要定义自己的Entity,通过DaoGenrator就能够生成对应的xxxDao对象。

新手接入

> 这里演示一个学生的例子

1.创建自己的Android Project,前戏就不贴了

2.导入greenDao

buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'    }}apply plugin: 'org.greenrobot.greendao'dependencies {    compile 'org.greenrobot:greendao:3.2.0'}

3.编写Entity
我们定义一个Student class:

@Entitypublic class Student {    @Id    private String mId;    private String mName;    private int mGender;}

@Entity和@Id是greenDao的标签,分别用来表示这是个Entity以及Entity的主键,greenDao Generator会根据这些标签自动生成DaoMaster、DaoSession、StudentDao。 具体的标签的使用方法可以查看官方文档。

4、点击Run, 最后生成的代码如下(部分加了注释):

DaoMaster.java

// 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(Database db, boolean ifNotExists) {        StudentDao.createTable(db, ifNotExists);    }    /** Drops underlying database table using DAOs. */    public static void dropAllTables(Database db, boolean ifExists) {        StudentDao.dropTable(db, ifExists);    }    /**     * WARNING: Drops all table on Upgrade! Use only during development.     * Convenience method using a {@link DevOpenHelper}.     */    public static DaoSession newDevSession(Context context, String name) {        Database db = new DevOpenHelper(context, name).getWritableDb();        DaoMaster daoMaster = new DaoMaster(db);        return daoMaster.newSession();    }    public DaoMaster(SQLiteDatabase db) {        this(new StandardDatabase(db));    }    public DaoMaster(Database db) {        super(db, SCHEMA_VERSION);        registerDaoClass(StudentDao.class);    }    public DaoSession newSession() {        return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);    }    public DaoSession newSession(IdentityScopeType type) {        return new DaoSession(db, type, daoConfigMap);    }    /**     * Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -     */    public static abstract class OpenHelper extends DatabaseOpenHelper {        public OpenHelper(Context context, String name) {            super(context, name, SCHEMA_VERSION);        }        public OpenHelper(Context context, String name, CursorFactory factory) {            super(context, name, factory, SCHEMA_VERSION);        }        @Override        public void onCreate(Database 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) {            super(context, name);        }        public DevOpenHelper(Context context, String name, CursorFactory factory) {            super(context, name, factory);        }        @Override        public void onUpgrade(Database db, int oldVersion, int newVersion) {            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");            //数据库升级。。。非常霸道,直接清除表后重建,我们实际项目中肯定不会这么使用的            dropAllTables(db, true);            onCreate(db);        }    }}

DaoSession.java :

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT./** * {@inheritDoc} *  * @see org.greenrobot.greendao.AbstractDaoSession */public class DaoSession extends AbstractDaoSession {    private final DaoConfig studentDaoConfig;    private final StudentDao studentDao;    public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>            daoConfigMap) {        super(db);        studentDaoConfig = daoConfigMap.get(StudentDao.class).clone();        //设置缓存类型        studentDaoConfig.initIdentityScope(type);        studentDao = new StudentDao(studentDaoConfig, this);        registerDao(Student.class, studentDao);    }    //清除缓存    public void clear() {        studentDaoConfig.clearIdentityScope();    }    public StudentDao getStudentDao() {        return studentDao;    }}

StudentDao.java

// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT./**  * DAO for table "STUDENT".*/public class StudentDao extends AbstractDao<Student, String> {    public static final String TABLENAME = "STUDENT";    /**     * 定义Studnet表的Column     */    public static class Properties {        public final static Property MId = new Property(0, String.class, "mId", true, "M_ID");        public final static Property MName = new Property(1, String.class, "mName", false, "M_NAME");        public final static Property MGender = new Property(2, int.class, "mGender", false, "M_GENDER");    }    public StudentDao(DaoConfig config) {        super(config);    }    public StudentDao(DaoConfig config, DaoSession daoSession) {        super(config, daoSession);    }    /** 创建Student表,这种创建方法有点太low了居然i无法做到自动创建 */    public static void createTable(Database db, boolean ifNotExists) {        String constraint = ifNotExists? "IF NOT EXISTS ": "";        db.execSQL("CREATE TABLE " + constraint + "\"STUDENT\" (" + //                "\"M_ID\" TEXT PRIMARY KEY NOT NULL ," + // 0: mId                "\"M_NAME\" TEXT," + // 1: mName                "\"M_GENDER\" INTEGER NOT NULL );"); // 2: mGender    }    /** Drops the underlying database table. */    public static void dropTable(Database db, boolean ifExists) {        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"STUDENT\"";        db.execSQL(sql);    }    /**     * 插入语句时绑定的数据,这种写法有点坑,万一MId为空时,生成的语句就有w     */    @Override    protected final void bindValues(DatabaseStatement stmt, Student entity) {        stmt.clearBindings();        String mId = entity.getMId();        if (mId != null) {            stmt.bindString(1, mId);        }        String mName = entity.getMName();        if (mName != null) {            stmt.bindString(2, mName);        }        stmt.bindLong(3, entity.getMGender());    }    @Override    protected final void bindValues(SQLiteStatement stmt, Student entity) {        stmt.clearBindings();        String mId = entity.getMId();        if (mId != null) {            stmt.bindString(1, mId);        }        String mName = entity.getMName();        if (mName != null) {            stmt.bindString(2, mName);        }        stmt.bindLong(3, entity.getMGender());    }    @Override    public String readKey(Cursor cursor, int offset) {        return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0);    }        /**     * 从sql读取数据,生成student对象     */    @Override    public Student readEntity(Cursor cursor, int offset) {        Student entity = new Student( //            cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // mId            cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // mName            cursor.getInt(offset + 2) // mGender        );        return entity;    }    @Override    public void readEntity(Cursor cursor, Student entity, int offset) {        entity.setMId(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));        entity.setMName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));        entity.setMGender(cursor.getInt(offset + 2));     }    @Override    protected final String updateKeyAfterInsert(Student entity, long rowId) {        return entity.getMId();    }    @Override    public String getKey(Student entity) {        if(entity != null) {            return entity.getMId();        } else {            return null;        }    }    @Override    public boolean hasKey(Student entity) {        return entity.getMId() != null;    }    @Override    protected final boolean isEntityUpdateable() {        return true;    }}

5.使用
- 初始化数据库

DevOpenHelper helper = new DevOpenHelper(this, "students");Database db = helper.getWritableDb();mDaoSession = new DaoMaster(db).newSession();mStudentDao = mDaoSession.getStudentDao();
  • 添加
Student student = new Student();student.setMId(String.valueOf(System.currentTimeMillis()));student.setMName("name"+System.currentTimeMillis());student.setMGender((int) (System.currentTimeMillis()%2));mStudentDao.insert(student);
  • 删除
final Student deleteStudent = mStudentDao.queryBuilder().orderDesc(StudentDao.Properties.MId).limit(1).unique();mStudentDao.delete(deleteStudent);

小结

从上面的demo,可以看到访问数据库的过程变得非常的简单。开发者只需要定义自己的entity,greenDao Generator就能自动生成对应的类文件。整个使用过程非常简单,但是,一般说到但是,就是来讲它的坏话了。。。我们也看到greenDao有如下几个问题:

  1. greenDao Generator仍然有点笨,生成的代码真心是笨(如:要是我们的变量是以m开头,则会生成 getM,setM方法。),还需要我们进一步加工,才能变成比较美观的代码。

  2. greenDao的DaoMaster在数据库的创建以及更新上都使用了指定sql语句的方法,比较笨拙,虽然网上有一个叫做MigrationHelper的解决方案,但仍不够友好。后续再给大家介绍一下我们使用的方法。

  3. xxxDao的Property支持的属性有限

如:Property.java

public final int ordinal;public final java.lang.Class<?> type;public final java.lang.String name;public final boolean primaryKey;public final java.lang.String columnName;

不支持default、is null、unique 等属性


Reference: https://github.com/greenrobot/greenDAO

0 0
原创粉丝点击