Android数据库选型

一、GreenDao和其他数据库对比

1、GreenDao官方提供的和GreenDao ,OrmLite,ActiveAndroid三者的 性能对比

GreenDao和其他数据库单位时间操作数据效率对比.png

通过对比,可以看到GreenDao无论在insert、update、query操作中效率都是最高的。

2、GreenDao和Realm性能对比(数据来源

分别操作1、10、100、1000、10000、100000条数据用时.png

二、各个数据库的优缺点。

1、 Ormlite

优点:

1.轻量级;
2.使用简单,易上手;
3.封装完善;
4文档完善,使用的项目比较多遇到问题查找比较方便.

缺点:

 基于注解和反射,方面效率会受到一些影响(不过要比直接使用SQL效率高)

2、GreenDao

优点:

  1、轻量(GreenDao核心类库只有100k左右)

  2、效率高、稳定(github上一直在维护更新,现在GreenDao版本已经更新到3.2.2)

  3、使用非常简单,上手快,可以自动生成代码

  4、支持数据库加密

  5、支持缓存(能够将使用的过的实体存在缓存中,下次使用时可以直接从缓存中取,这样可以使性能提高N个数量级)
 6、支持与rxjava结合使用

缺点:

 文档大部分是英文的

官方对GreenDao性能的描述: Of all ORMs we know, greenDAO is the fastest. greenDAO does not make any compromises regarding performance. Databases are great for storing lots of data, and thus speed matters. Using greenDAO, most entities can be inserted, updated and loaded at rates of several thousand entities per second.

集成过程:

【1】 在项目(project)的gradle中
// In your project build.gradle file:
buildscript {
   repositories {
      jcenter()
      mavenCentral() // add repository
   }
   dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
   }
}
【2】在应用(Moudle)的gradle中
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin

dependencies {
    compile 'org.greenrobot:greendao:3.2.2' // add library
}

配置数据库的信息
 greendao {
      schemaVersion 1   // 版本号 升级数据库可以配置
      daoPackage 'com.zgl.greentest.gen'  // 自动生成的代码的存放包名(可忽略)
      targetGenDir 'src/main/java'  // 自动生成代码的存放位置(可忽略)
}

使用:

  • 1.创建一个bean对象
    @Entity
    public class Shop{
        //表示为购物车列表
        public static final int TYPE_CART = 0x01;
        //表示为收藏列表
        public static final int TYPE_LOVE = 0x02;
        //不能用int
        @Id(autoincrement = true)
        private Long id;
        //商品名称
        @Unique
        private String name;
        //商品价格
        @Property(nameInDb = "price")
        private String price;
        //已售数量
        private int sell_num;
        //图标url
        private String image_url;
        //商家地址
        private String address;
        //商品列表类型
        private int type;
    }

注解含义: @Entity:告诉GreenDao该对象为实体,只有被@Entity注释的Bean类才能被dao类操作 @Id:对象的Id,使用Long类型作为EntityId,否则会报错。(autoincrement = true)表示主键会自增,如果false就会使用旧值 @Property:可以自定义字段名,注意外键不能使用该属性 @NotNull:属性不能为空 @Transient:使用该注释的属性不会被存入数据库的字段中 @Unique:该属性值必须在数据库中是唯一值 @Generated:编译后自动生成的构造函数、方法等的注释,提示构造函数、方法等不能被修改


  • 2.初始化greenDao
public class BaseApplication extends Application {
private static BaseApplication mBaseApplication;
private DaoSession mDaoSession;

@Override
public void onCreate() {
    super.onCreate();

    mBaseApplication = this;

    initDataBase();
}

public static BaseApplication instance(){
    return mBaseApplication;
}

// 初始化数据库
private void initDataBase() {
    //创建数据库shop.db"
    DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "shop.db", null);
    //获取可写数据库
    SQLiteDatabase db = helper.getWritableDatabase();
    //获取数据库对象
    DaoMaster daoMaster = new DaoMaster(db);
    //获取Dao对象管理者
    daoSession = daoMaster.newSession();
}

public DaoSession getDaoSession() {
    return mDaoSession;
}
}
  • 3.数据库增删改查
private ShopDao mShopDao = GreenDaoManager.getInstance().getDaoSession().getBookEntityDao();
private Shop dogEntity = new Shop();

private void greenDaoQuery() {
    mShopDao.loadAll();
    mShopDao.queryBuilder().where(ShopEntityDao.Properties.Price.eq("10"));
}

private void greenDaoUpdate() {
    mShopDao.update(dogEntity);
}

private void greenDaoDelete() {
    mShopDao.deleteAll();
}

private void greenDaoInsert() {
    mShopDao.insert(dogEntity);
 }

GreenDao官网

3、Realm

Ream 不是在SQLite基础上的ORM,它有自己的数据查询引擎。所以支持跨平台,也更加高效

优点:

 1、支持跨平台(Android,ios,swift)
 2、可视化比较好,realm提供了数据库可视化工具
 3、效率高(插入和删除数据比GreenDao还要快,但是删除数据会比GreenDao稍慢一些)
 4、支持rxjava异步操作
 5、支持加密操作

集成过程:

 buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath "io.realm:realm-gradle-plugin:3.1.3"
    }
 }
apply plugin: 'realm-android'

使用:

  • 1.创建一个bean

所有realm的bean都需要集成 RealmObject

eg:
public class User extends RealmObject {
    private String          name;  // realm的修饰符支持private public protect
    private int             age;

    @Ignore
    private int             sessionId;

    // Standard getters & setters generated by your IDE…
    public String getName() { return name; }
    public void   setName(String name) { this.name = name; }
    public int    getAge() { return age; }
    public void   setAge(int age) { this.age = age; }
    public int    getSessionId() { return sessionId; }
    public void   setSessionId(int sessionId) { this.sessionId = sessionId; }
}

注解: @PrimaryKey——表示该字段是主键 @Required——表示该字段非空 @Ignore——表示忽略该字段 被添加@Ignore标签后,存储数据时会忽略该字段。 @Index——添加搜索索引 为字段添加搜索索引,这样会使得插入的速度变慢,数据量也变得更大。不过在查询速度将变得更快,建议只在优化读取性能的特定情况时添加索引

  • 2.初始化realm
    Realm.init(this);
    Realm mRealm = Realm.getDefaultInstance();

也可以配置realm的参数

  RealmConfiguration config = new RealmConfiguration.Builder() 
        .name("myrealm.realm") //文件名
        .schemaVersion(0) //版本号
        .build();
  Realm realm = Realm.getInstance(config);

当使用完毕需要在ondestory()中关闭realm

@Override 
protected void onDestroy() { 
    super.onDestroy();
    // Close the Realm instance. 
    realm.close(); 
}
  • 3.增删改查

插入数据

  realm.executeTransaction(new Realm.Transaction() {
     @Overrride
      public void execute(Realm realm) {
      Dog dog = realm.createObject(Dog.class);
      dog.name = "Fido";
      dog.age  = 5;
      }
  };

    也可以通过这种方式插入数据:
    // Obtain a Realm instance
    realm.beginTransaction();
    User user = realm.createObject(User.class); // Create a new object
    user.setName("John");
    user.setEmail("john@corporation.com");
    realm.commitTransaction();

realm操作的速度比较快,所以对于少量数据在主线程中操作没有太大影响,但是如果数据量大的话就需要在子线程中进行了

  realm异步插入数据:
    realm.executeTransactionAsync(new Realm.Transaction() {
        @Override
        public void execute(Realm bgRealm) {
            User user = bgRealm.createObject(User.class);
            user.setName("John");
            user.setEmail("john@corporation.com");
        }
    }, new Realm.Transaction.OnSuccess() {
        @Override
        public void onSuccess() {
            // Transaction was a success.
        }
    }, new Realm.Transaction.OnError() {
        @Override
        public void onError(Throwable error) {
            // Transaction failed and was automatically canceled.
        }
    });

查询

    RealmResults<User> userList = mRealm.where(User.class).findAll();

    异步查询
    RealmResults<User> userList = mRealm.where(User.class)
          .equalTo("name", "Gavin")
          .findAllAsync();

    按条件查询
    RealmResults<User> userList = mRealm.where(User.class)
     .equalTo("name", "Gavin").findAll();

    多条件查询
    RealmResult<User> r = realm.where(User.class)
                       .not()
                       .in("name", new String[]{"Peter", "Jo"})
                       finalAll();

其他查询条件 sum():对指定字段求和。 average():对指定字段求平均值。 min(): 对指定字段求最小值。 max() : 对指定字段求最大值。count : 求结果集的记录数量。 findAll(): 返回结果集所有字段,返回值为RealmResults队列 findAllSorted() : 排序返回结果集所有字段,返回值为RealmResults队列 between(), greaterThan(),lessThan(), greaterThanOrEqualTo() & lessThanOrEqualTo() equalTo() & notEqualTo() contains(), beginsWith() & endsWith() isNull() & isNotNull() isEmpty()& isNotEmpty()

排序

    RealmResults<User> result = realm.where(User.class).findAll();
    result = result.sort("age"); // Sort ascending
    result = result.sort("age", Sort.DESCENDING);

删除

 // obtain the results of a query
final RealmResults<Dog> results = realm.where(Dog.class).findAll();

// All changes to data must happen in a transaction
realm.executeTransaction(new Realm.Transaction() {
    @Override
    public void execute(Realm realm) {
        // remove single match
        results.deleteFirstFromRealm();
        results.deleteLastFromRealm();

        // remove a single object
        Dog dog = results.get(5);
        dog.deleteFromRealm();

        // Delete all matches
        results.deleteAllFromRealm();
    }
});

有关realm的更多操作可以参见这里

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 210,978评论 6 490
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 89,954评论 2 384
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,623评论 0 345
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,324评论 1 282
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,390评论 5 384
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,741评论 1 289
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,892评论 3 405
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,655评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,104评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,451评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,569评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,254评论 4 328
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,834评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,725评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,950评论 1 264
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,260评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,446评论 2 348

推荐阅读更多精彩内容