码迷,mamicode.com
首页 > 其他好文 > 详细

greenDAO用法总结

时间:2015-06-16 16:03:45      阅读:4432      评论:0      收藏:0      [点我收藏+]

标签:

简介:greendao是一个开源项目,帮助Android开发人员使用的数据存储在SQLite。是一个可怕的嵌入式SQLite关系数据库。然而,它 的发展需要大量的额外工作。解析和编写sql查询的结果是相当繁琐。greendao做工作:它的java对象映射到数据库表(通常称为orm),这样,你可以存储、更新、删除和查询,使用一个简单的Java对象,面向对象的API。节省的时间和关注的问题。

greendao’的主要设计目标

  • 性能最大最快的ORM(Android)
  • 易于使用的API
  • 高度优化的安卓系统
  • 最小的内存消耗
  • 小型图书馆规模,关注要点
技术分享
GreenDao与Ormlite对比
Ormlite:简单好用,比较符合JavaEE开发者使用习惯,注解很方便;
GreenDao:为Android大大优化 ,最小的内存使用 ,非常高的性能优势。
技术分享
使用步骤: 
1、从github上将项目下载下来,导入开发工具。下载地址:https://github.com/greenrobot/greenDAO   
2、其中有两个java项目,这两个java项目是用于生成bean文件和DaoMaster、DaoSession文件的,在示例文件中添加指定的bean,设置属性后运行java项目。
    此处注意,该项目运行java项目时,需要导入freemarker-xxx.jar,下载地址:http://freemarker.org/freemarkerdownload.html  ; 
    指定生成的目录时要填写src-gen,该目录必须在android项目中创建好,否则会报错;要写android项目的包名及项目路径 
3、生成完后,在android项目中刷新src-gen目录后找到生成的文件,在自定义application中,添加两个方法

下载后,相关包项目说明:
DaoCore                android工程源码 库目录,即jar文件greendao-1.3.0-beta-1.jar的代码;
DaoExample            android工程demo android范例工程
DaoExampleGenerator    实体生成demo DaoExample工程的DAO类构造器,java工程;
DaoGenerator        实体生成器源码  AO类构造器,java工程;
DaoTest、PerformanceTestOrmLite:其他测试相关的工程。
(一)DAO类构造
技术分享
运行后可以看到,DaoExample项目src-gen下面自动生成了8个文件,3个实体对象,3个dao,1个DaoMaster,1个DaoSession.
ps:可以自己实现greenDao与Parcelable使用总结;
    Parcelable是Android中用于对Object数据进行序列化和反序列化的接口。
    注意:greendao自动生成的info可以继承Parcelable接口,实现序列化和反序列数据存储。(可以通过as自动生成)
  1. package de.greenrobot.daogenerator.gentest;
  2. import de.greenrobot.daogenerator.DaoGenerator;
  3. import de.greenrobot.daogenerator.Entity;
  4. import de.greenrobot.daogenerator.Property;
  5. import de.greenrobot.daogenerator.Schema;
  6. import de.greenrobot.daogenerator.ToMany;
  7. /**
  8. * @description:
  9. 使用说明:
  10. 0.android工程导入dist/greendao-xxx.jar
  11. 1.用实体生成demo,生成相应的实体及其数据库操作类
  12. 2.(可选)对上述数据库操作类进行service层的封装
  13. 3.修改DaoMaster中数据库名称及debug等参数
  14. 4.最好单例化DaoMaster,并在application中进行初始化
  15. 5.(在通过service中)创建DaoSession,获取相应dao进行实体的数据库相关操作
  16. 6.参考链接(异或百度)
  17. 官网http://greendao-orm.com/
  18. 源码https://github.com/greenrobot/greenDAO
  19. 更新说明
  20. 2014-10-31
  21. DaoCore android工程源码
  22. DaoExample android工程demo
  23. DaoExampleGenerator 实体生成demo
  24. DaoGenerator 实体生成器源码
  25. * @author samy
  26. * @date 2015-4-27 下午5:28:22
  27. */
  28. public class ExampleDaoGenerator {
  29. // (1)创建Java工程
  30. // (2)导入greenDao-generator.jar和freemarker.jar两个包。
  31. // freemarker是一个用java写的模板引擎,它能够基于模板来生成文本输出。应该就是用来自动生成DAO文件的。
  32. /**
  33. * @description:(3)创建schema
  34. * @author samy
  35. * @date 2015年6月15日 下午4:29:11
  36. */
  37. public static void main(String[] args) throws Exception {
  38. // 创建schema时需要制定数据库的版本号、默认的Java package等参数。
  39. Schema schema = new Schema(1001, "com.zsy.sample.support.db.onepiececategory");
  40. // 默认Java package用来存放生成的entity、DAO文件、test代码。但也可以重新制定test文件的单独路径以及DAO文件的路径,代码:
  41. // schema.setDefaultJavaPackageTest("de.greenrobot.daoexample.test");
  42. // schema.setDefaultJavaPackageDao("de.greenrobot.daoexample.dao");
  43. // 另外,还有两个flag,用来标示entity是否是activie以及是否使用keep sections。代码:
  44. schema.enableKeepSectionsByDefault();
  45. // schema2.enableActiveEntitiesByDefault();
  46. // Keep sections:因为entity class在每次generator执行时均会覆盖原来的程序,为了能够添加用户自定义代码到entity中,需要设置该参数。只需要把自己的代码添加到下面的KEEP[]块中间就可以了。
  47. // KEEP INCLUDES - put your custom includes here
  48. // KEEP INCLUDES END
  49. // ...
  50. // KEEP FIELDS - put your custom fields here
  51. // KEEP FIELDS END
  52. // ...
  53. // KEEP METHODS - put your custom methods here
  54. // KEEP METHODS END
  55. addProductCategory(schema);
  56. // addCustomerOrder(schema);
  57. /**
  58. *(5)生成DAO文件 生成DAO文件就是使用main函数的最后一句话,其中后面的参数就是希望自动生成的代码对应的项目路径。
  59. * 注:设置的路径必须存在,否则会抛出异常。该路径是另外的工程下面的目录,当然也可以自己不这么做,只要这个目录存在就行。在schema创建的时候指定的package接口也是相对于该路径的。
  60. */
  61. new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
  62. }
  63. private static void addProductCategory(Schema schema) {
  64. Entity note = schema.addEntity("OnePieceCategory");
  65. note.addIdProperty();
  66. note.addStringProperty("typeId");
  67. note.addStringProperty("typeName");
  68. note.addStringProperty("typeImage");
  69. note.addIntProperty("levelNum");
  70. note.addIntProperty("orderBy");
  71. note.addStringProperty("parentId");
  72. note.addStringProperty("webTypeImage");
  73. }
  74. private static void addNote(Schema schema) {
  75. Entity note = schema.addEntity("OncePieceCategory");
  76. note.addIdProperty();
  77. note.addStringProperty("typeId");
  78. note.addStringProperty("typeName");
  79. note.addStringProperty("parentId");
  80. }
  81. /**
  82. * @description:(4)创建entity
  83. * schema中可以添加entity,简单的理解应该是entity对应一个具体的java class,entity可以添加property。Entity通常也是对应一个table。
  84. * 除了添加property之外,entity也可以添加to-one和to-many关系,即添加一对一的关系和一对多的关系。
  85. * @author samy
  86. * @date 2015年6月15日 下午4:28:51
  87. */
  88. private static void addCustomerOrder(Schema schema) {
  89. Entity customer = schema.addEntity("Customer");
  90. customer.addIdProperty();
  91. customer.addStringProperty("name").notNull();
  92. Entity order = schema.addEntity("Order");
  93. order.setTableName("ORDERS"); // "ORDER" is a reserved keyword
  94. order.addIdProperty();
  95. Property orderDate = order.addDateProperty("date").getProperty();
  96. Property customerId = order.addLongProperty("customerId").notNull().getProperty();
  97. order.addToOne(customer, customerId);
  98. ToMany customerToOrders = customer.addToMany(order, customerId);
  99. customerToOrders.setName("orders");
  100. customerToOrders.orderAsc(orderDate);
  101. }
  102. }

查询:

(1)QueryBuilder

    使用过sql语句查询的人都会有一种感触(主要针对不是专职开发数据库并对sql不是很熟练的人),写起来复杂、不能再第一时间发现问题(只能在运行过程中验证sql的正确性)、查找bug麻烦等等。QueryBuilder的出现就是为了解决sql使用的问题,提高开发效率。

看一个略微复杂的例子,查询first name是Joe,并在1970年10月以及之后的所有人:

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();

(2)Lazylist

    greenDAO支持返回唯一查询结果(如果没有返回null) ---- 调用Query或QueryBuilder的unique()方法;

    也支持返回list ---- 调用list()方法。

    当不希望返回null作为结果时,则调用uniqueOrThrow()方法,当结果null时将直接抛出异常。

返回多个结果解释:

list():     所有entity均会被加载到内存中。结果仅是一个简单的ArrayList。使用最简单。

listLazy():    查询结果会根据需要加载到内存中。列表中的元素仅在accessed for the first time,它才会被加载并缓存。该方法必须主动关闭(Must be closed)。

listLazyUncached():    虚拟的结果列表,任何对元素的方法实际都会到数据库中去加载数据。Must be closed

listIterator():    根据需要迭代结果(lazily)。数据不缓存。Must be closed


在greenDAO实现中,后3中其实都使用的LazyList类。为了实现根据需要加载,其内部实现上是保存了数据库cursor的引用。这也是为何这3中方式must be closed,其就是为了释放内部cursor和迭代器(通常是在try-finally块中完成close)。


(3)Query

    解释:Query类代表了一个可以被重复执行的查询。在QueryBuilder内部其实也是会定义一个Query并执行完成查询。

    这将带来极大地方便,因为任何人都不希望在每次查询的时候总是写一遍query代码。同时Query还可以根据需要改变参数。如下实例代码:

    使用Query对象查询名为Joe并出生在1970年的人:

Query query = userDao.queryBuilder().where(

Properties.FirstName.eq("Joe")Properties.YearOfBirth.eq(1970))

.build();

List joesOf1970 = query.list();

然后想再查询出生在1977年之后并叫Marias的人:

query.setParameter(0"Maria");

query.setParameter(11977);

List mariasOf1977 = query.list();

注意:参数的编号是创建query所设置的顺序。


(4)多线程查询

    有时我们希望在多线程中执行查询。从greenDAO 1.3版本开始,实例化Query对象均会绑定到其自己的线程,这样我们就可以安全的设置Query参数,因为其他线程无法影响到。如果其他线程使用别的线程的query(比如设置参数、执行查询)将会抛出异常。因此,我们也不需要做同步工作,而且不要加锁,因为加入相关的事务用到了该Query对象将导致死锁。

    为完全地避免可能产生的死锁,1.3版本引入了forCurrentThread()方法。该方法将返回本线程内的Query实例,每次调用该方法时,参数均会被重置为最初创建时的一样。


(5)原生sql查询

    推荐的方法执行原生sql语句是通过QueryBuilder和WhereCondition.StringCondition。如下代码:

Query query = userDao.queryBuilder().where(

new StringCondition("_ID IN " "(SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)").build();

    假如QueryBuilder没有提供你需要的特性,你也可以使用queryRaw() 和 queryRawCreate() 方法。具体就不再详细介绍了。


(6)删除操作(delete query)

    删除操作会删除所有满足条件的实体。为实现批量删除(bulk delete),调用QueryBuilder的 buildDelete方法并执行DeleteQuery。该部分API还不稳定,可能会改变就不介绍了。


(7)问题定位(日志

    你可能会遇到查询结果并不是预期的那样,这时候你就可以设置两个静态flag参数来打日志定位问题:

QueryBuilder.   LOG_SQL       =       true   ;
QueryBuilder.   LOG_VALUES       =       true   ;

    这将会将产生的sql命令以及传递的参数以日志方式输出,由此方便程序员定位问题。


使用:(增删改查操作)

1.查询

范例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;
}

 范例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
{
return
}
else
{
return
}
}

范例4:查找所有第一姓名是“Joe”并且以lastname排序。

List joes = userDao.queryBuilder()

where(Properties.FirstName.eq("Joe"))
orderAsc(Properties.LastName)
list();

范例5:多重条件查询

(1)获取id为cityId并且infotype为HBContant.CITYINFO_SL的数据集合:

public List<CityInfoDB> getSupportingList(int cityId)
{
QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
qb.where(qb.and(Properties.CityId.eq(cityId),Properties.InfoType.eq(HBContant.CITYINFO_SL)));
qb.orderAsc(Properties.Id);
return
}

(2)获取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();

范例6:获取某列对象

picJsonDao.loadByRowId(picId);

2.增添/插入、修改

插入数据更加简单,也是只要一句代码便能搞定!

public void addToPhotoTable(Photo p)
{
photoDao.insert(p);
}

插入时需要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);

修改更新:

photoDao.insertOrReplace(photo);
photoDao.insertInTx(photo);
categoryDaoSession.runInTx(new Runnable() { @Override public void run() {
                               OnePieceCategoryDao.dropTable(db, true);
                               OnePieceCategoryDao.createTable(db, true);  
                                for (OnePieceCategory category : list) {
                                    categoryDao.insert(category);
                                    count++;
                                 }
                               
                            }
}



3.删除:

(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();
}

参考:https://github.com/greenrobot/greenDAO/issues/34

由上可见,使用greenDAO进行数据库的增删改查时及其方便,而且性能极佳。


(三)常用方法笔记
1.在Application实现得到DaoMaster和DaoSession的方法:
  1. private static DaoMaster daoMaster;
  2. private static DaoSession daoSession;
  3. /**
  4. * 取得DaoMaster
  5. *
  6. * @param context
  7. * @return
  8. */
  9. public static DaoMaster getDaoMaster(Context context)
  10. {
  11. if (daoMaster == null)
  12. {
  13. OpenHelper helper = new DaoMaster.DevOpenHelper(context, HBContant.DATABASE_NAME, null);
  14. daoMaster = new DaoMaster(helper.getWritableDatabase());
  15. }
  16. return daoMaster;
  17. }
  18. /**
  19. * 取得DaoSession
  20. *
  21. * @param context
  22. * @return
  23. */
  24. public static DaoSession getDaoSession(Context context)
  25. {
  26. if (daoSession == null)
  27. {
  28. if (daoMaster == null)
  29. {
  30. daoMaster = getDaoMaster(context);
  31. }
  32. daoSession = daoMaster.newSession();
  33. }
  34. return daoSession;
  35. }
2.增删改查工具类:
  1. public class DBHelper
  2. {
  3. private static Context mContext;
  4. private static DBHelper instance;
  5. private CityInfoDBDao cityInfoDao;
  6. private DBHelper()
  7. {
  8. }
  9. public static DBHelper getInstance(Context context)
  10. {
  11. if (instance == null)
  12. {
  13. instance = new DBHelper();
  14. if (mContext == null)
  15. {
  16. mContext = context;
  17. }
  18. // 数据库对象
  19. DaoSession daoSession = HBApplication.getDaoSession(mContext);
  20. instance.cityInfoDao = daoSession.getCityInfoDBDao();
  21. }
  22. return instance;
  23. }
  24. /** 添加数据 */
  25. public void addToCityInfoTable(CityInfo item)
  26. {
  27. cityInfoDao.insert(item);
  28. }

  29. /** 查询 */
  30. public List<EstateLoveListJson> getCityInfoList()
  31. {
  32. QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
  33. return qb.list();
  34. }

  35. /** 查询 */
  36. public List<CityInfo> getCityInfo()
  37. {
  38. return cityInfoDao.loadAll();// 查找图片相册
  39. }
  40. /** 查询 */
  41. public boolean isSaved(int Id)
  42. {
  43. QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
  44. qb.where(Properties.Id.eq(Id));
  45. qb.buildCount().count();
  46. return qb.buildCount().count() > 0 ? true : false;// 查找收藏表
  47. }
  48. /** 删除 */
  49. public void deleteCityInfoList(int Id)
  50. {
  51. QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
  52. DeleteQuery<CityInfo> bd = qb.where(Properties.Id.eq(Id)).buildDelete();
  53. bd.executeDeleteWithoutDetachingEntities();
  54. }
  55. /** 删除 */
  56. public void clearCityInfo()
  57. {
  58. cityInfoDao.deleteAll();
  59. }
  60. /** 通过城市id查找其类型id */
  61. public int getTypeId(int cityId)
  62. {
  63. QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
  64. qb.where(Properties.Id.eq(cityId));
  65. if (qb.list().size() > 0)
  66. {
  67. return qb.list().get(0).getTypeId();
  68. }
  69. else
  70. {
  71. return 0;
  72. }
  73. }
  74. /** 多重查询 */
  75. public List<CityInfo> getIphRegionList(int cityId)
  76. {
  77. QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
  78. qb.where(qb.and(Properties.CityId.eq(cityId), Properties.InfoType.eq(HBContant.CITYINFO_IR)));
  79. qb.orderAsc(Properties.Id);// 排序依据
  80. return qb.list();
  81. }
  82. }
另外,还有多表关联、惰性加载等功能,待后续研究。

greenDao混淆

对greenDao混淆要写一下代码

-libraryjars libs/greendao-1.3.7.jar

-keep class de.greenrobot.dao.** {*;}

#保持greenDao的方法不被混淆

-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {

#用来保持生成的表名不被混淆     public static java.lang.String TABLENAME; } -keep class **$Properties

 

greenDAO用法总结

标签:

原文地址:http://www.cnblogs.com/hongfeiliuxing/p/4580806.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!