android高效ORM数据库框架greenDao使用
因为项目中多处用到了数据库,需要对数据库频繁的读写操作,虽然android 自带的SQLiteOpenHelper的.这种方式比较方便易懂,但是在使用过程中需要写很多的sql语句,而且需要及时的关闭和释放资源,使用起来相对复杂,鉴于性能的考虑,决定采用一种ORM框架来解决,
在android中开源的数据库ORM解决方案中.主要有那么几种.综合各方面评价,觉得greenDao相对来说是一个综合考量最好的方案,所以决定试一下,
但是greenDao使用相关资料网上确实不多,仅有的官网介绍也是言简意赅,自己捣鼓了下,也算是实现了相关的功能,而且性能还是不错的,记录一下.以防不时之需.\
一: greenDao介绍
1. 官网:http://greendao-orm.com/,从官网的图片看出还是相当小清新的哈,
2,项目下载地址:https://github.com/greenrobot/greenDAO(github),也可以选择在官网下载.
3.greenDAO的主要设计目标:
*最大性能(最快的 Android ORM)
*易于使用API
*高度优化
*最小内存消耗
二: 实例
好了,废话不多说,先看一下官方文档的介绍入手来进行greenDao的使用,首先下载相关工程项目.官网上的指引,也是叫我们上github下载,下载下来是包含了好几个工程的,因为项目比较老了,所以采用的是eclipse结构的,我们可以使用eclipse直接导入 使用,其中包括:
DaoCore :库文件源代码.编译后的jar包导入项目即可使用.
DaoExample:这个就是sample了.
DaoExampleGenerator:DaoExample工程的DAO类构造器,java工程,用于生成数据库相关文件.
DaoTest、PerformanceTestOrmLite:其他测试相关的工程
ExampleDaoGenerator
/* * Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package de.greenrobot.daogenerator.gentest; import de.greenrobot.daogenerator.DaoGenerator; import de.greenrobot.daogenerator.Entity; import de.greenrobot.daogenerator.Property; import de.greenrobot.daogenerator.Schema; import de.greenrobot.daogenerator.ToMany; /** * Generates entities and DAOs for the example project DaoExample. * * Run it as a Java application (not Android). * * @author Markus */ public class ExampleDaoGenerator { public static void main(String[] args) throws Exception { // //第一个参数是DB的版本号,通过更新版本号来更新数据库。第二个参数是自动生成代码的包路径 Schema schema = new Schema(1000, "de.greenrobot.daoexample"); addNote(schema); addCustomerOrder(schema); // 希望自动生成的代码对应的项目路径 //src-gen这个文件夹必须手动创建,这里路径如果错了会抛出异常 new DaoGenerator().generateAll(schema, "../DaoExample/src-gen"); } private static void addNote(Schema schema) { Entity note = schema.addEntity("Note"); note.addIdProperty(); note.addStringProperty("text").notNull(); note.addStringProperty("comment"); note.addDateProperty("date"); } private static void addCustomerOrder(Schema schema) { Entity customer = schema.addEntity("Customer"); customer.addIdProperty(); customer.addStringProperty("name").notNull(); Entity order = schema.addEntity("Order"); order.setTableName("ORDERS"); // "ORDER" is a reserved keyword order.addIdProperty(); Property orderDate = order.addDateProperty("date").getProperty(); Property customerId = order.addLongProperty("customerId").notNull().getProperty(); order.addToOne(customer, customerId); ToMany customerToOrders = customer.addToMany(order, customerId); customerToOrders.setName("orders"); customerToOrders.orderAsc(orderDate); } }
greenDao 使用的难点其实就是入门,最开始需要创建一个如上的 Java工程来生成相应的DaoMaster,DaoSession,.和相应的JavaBean及DAO.
通过addIdProperty(); 添加ID属性,如果希望是自增长的,则需要添加上autoincrement();即可.
同时,支持很多中数据类型.可以通过添加notNull() 和unique() ;添加非空和唯一性约束.
note.addStringProperty("noteId").notNull().unique(); note.addBooleanProperty("isNew"); note.addStringProperty("text"); note.addStringProperty("type");
此Java工程需要导入greendao-generator-1.3.1.jar jar包.Java工程创建好了之后,就可以运行他了,此时,如果生成了类似一下的日志,则说明创建成功了
greenDAO Generator Copyright 2011-2013 Markus Junginger, greenrobot.de. Licensed under GPL V3. This program comes with ABSOLUTELY NO WARRANTY Processing schema version 3... Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleNoteDao.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleNote.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleCustomerDao.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleCustomer.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleOrderDao.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleOrder.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleDaoMaster.java Written F:Android_Exwork_10DaoExamplesrc-gendegreenrobotdaoexampleDaoSession.java Processed 3 entities in 204ms
有时,也可能出现类似下面的错误/
Exception in thread "main" java.io.FileNotFoundException: Template "dao.ftl" not found. at freemarker.template.Configuration.getTemplate(Configuration.java:742) at freemarker.template.Configuration.getTemplate(Configuration.java:665) at de.greenrobot.daogenerator.DaoGenerator.(DaoGenerator.java:68) at de.greenrobot.daogenerator.gentest.ExampleDaoGenerator.main(ExampleDaoGenerator.java:41)
这是很常见的io异常,看看是否目标文件夹没有创建的缘故,抑或clean一下试试.
greenDao会自动根据实体类属性来创建 表 字段病赋予 相应的默认值.在数据库方面的表名和列名都来源于实体类名和属性名。默认的数据库名称是大写使用下划线分隔单词,而不是在Java中使用的驼峰式大小写风格。例如,一个名为“CREATIONDATE”属性将成为一个数据库列“CREATION_DATE”。
三: 增删改查
greenDao对数据库表的操作也是相当的方便,完全的面向对象,不用写sql语句,
一 查询:
1.查询某个表是否包含某个id
public boolean isSaved(int ID){ QueryBuilder<SaveList> qb = saveListDao.queryBuilder(); qb.where(Properties.Id.eq(ID)); qb.buildCount().count(); return qb.buildCount().count() > 0 ? true : false; }
我们需要利用一个叫做QueryBuilder 的东西,这个东西是可以重复利用的,因此在后面我们需要创建一个工具类来将这些数据库的操作封装起来.
2. 获取某个表中的所有对象,以集合的形式返回
public List<PhotoGalleryDB> getPhotoGallery() { return photoGalleryDao.loadAll();// 获取图片相册 }
3.通过一个字段值查找对应的另一个字段值
/** 通过图片id查找其目录id */ public int getTypeId(int picId){ QueryBuilder<PhotoGalleryDB> qb = photoGalleryDao.queryBuilder(); qb.where(Properties.Id.eq(picId)); if (qb.list().size() > 0){ return qb.list().get(0).getTypeId(); }else{ return -1; } }
4. 查找所有第一姓名是“Joe”并且以lastname排序。
List joes = userDao.queryBuilder() .where(Properties.FirstName.eq("Joe")) .orderAsc(Properties.LastName) .list();
5. 多重条件查询,获取firstname为“Joe”并且出生于1970年10月以后的所有user集合
QueryBuilder qb = userDao.queryBuilder(); qb.where(Properties.FirstName.eq("Joe"), qb.or(Properties.YearOfBirth.gt(1970), qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10)))); List youngJoes = qb.list();
二增添/插入、修改
1. 插入数据更加简单,也是只要一句代码便能搞定!插入时需要new一个新的对象
DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null); db = helper.getWritableDatabase(); daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); noteDao = daoSession.getNoteDao(); Note note = new Note(null, noteText, comment, new Date()); noteDao.insert(note);
2.修改更新:
photoDao.insertOrReplace(photo);
photoDao.insertInTx(photo);
三:删除
1. 清除数据库
/** 清空相册图片列表的数据 */ public void clearPhoto(){ photoDao.deleteAll(); }
2. 删除某个对象
public void deleteCityInfo(int cityId){ QueryBuilder<DBCityInfo> qb = cityInfoDao.queryBuilder(); DeleteQuery<DBCityInfo> bd = qb.where(Properties.CityId.eq(cityId)).buildDelete(); bd.executeDeleteWithoutDetachingEntities(); }
更多用法参考:http://greendao-orm.com/documentation/
四: 常用方法总结
package com.example.drugazdbdemo; import android.app.Application; import android.content.Context; import com.example.drugazdbdemo.DaoMaster.OpenHelper; public class BaseApplication extends Application { private static BaseApplication mInstance; private static DaoMaster daoMaster; private static DaoSession daoSession; @Override public void onCreate() { super.onCreate(); if (mInstance == null) mInstance = this; } /** * 取得DaoMaster * * @param context * @return */ public static DaoMaster getDaoMaster(Context context, String TABLENAME) { if (daoMaster == null) { OpenHelper helper = new DaoMaster.DevOpenHelper(context, TABLENAME, null); daoMaster = new DaoMaster(helper.getWritableDatabase()); } return daoMaster; } /** * 取得DaoSession * * @param context * @return */ public static DaoSession getDaoSession(Context context, String TABLENAME) { if (daoSession == null) { if (daoMaster == null) { daoMaster = getDaoMaster(context, TABLENAME); } daoSession = daoMaster.newSession(); } return daoSession; } }
一般情况下.我们需要新建一个BaseApplication类继承自Application,这样的话,可以减少重复新建DaoMaster和DaoSession.
同时,我们可以新建一个泛型类来操作数据库,,封装数据库的增删改查方法./
package com.yaodu.drug.database; import android.content.Context; import com.yaodu.application.MyApplication; import java.util.List; import de.greenrobot.dao.AbstractDao; import de.greenrobot.dao.query.DeleteQuery; import de.greenrobot.dao.query.QueryBuilder; import de.greenrobot.dao.query.WhereCondition; @SuppressWarnings({"rawtypes", "unchecked"}) public class DbService<T> { private static DbService instance; private DaoSession mDaoSession; private AbstractDao<T, Long> tDao; private DbService() { } public static DbService getInstance(Context context, String TABLENAME, Class bean) { if (instance == null) { instance = new DbService(); } instance.mDaoSession = MyApplication .getDaoSession(context, TABLENAME); instance.tDao = instance.mDaoSession.getDao(bean); return instance; } public List<T> loadAllT() { return tDao.loadAll(); } public List<T> queryTLists(WhereCondition where) { QueryBuilder<T> builder = instance.tDao.queryBuilder(); return builder.where(where).list(); } public List<T> queryTLists(QueryBuilder<T> builder,WhereCondition where){ return builder.where(where).list(); } public QueryBuilder<T> getQueryBuilder(){ return instance.tDao.queryBuilder(); } public T updateT(T t) { tDao.update(t); return t; } /** * insert or update noteList use transaction */ public void saveTLists(final List<T> list) { if (list == null || list.isEmpty()) { return; } tDao.getSession().runInTx(new Runnable() { @Override public void run() { for (int i = 0; i < list.size(); i++) { T t = list.get(i); tDao.insertOrReplace(t); } } }); } public void deleteById(String mId) { QueryBuilder<T> builder = instance.tDao.queryBuilder(); DeleteQuery<T> bd = builder.where(tDao.getProperties()[1].eq(mId)).buildDelete(); bd.executeDeleteWithoutDetachingEntities(); } }