转:

http://www.it165.net/pro/html/201401/9026.html

  • 最近在对开发项目的性能进行优化。由于项目里涉及了大量的缓存处理和数据库运用,需要对数据库进行频繁的读写、查询等操作。因此首先想到了对整个项目的数据库框架进行优化。

    原先使用android本身内置的sqllite,也就是用的最基本的SQLiteOpenHelper方法,这种方法对自己来说比较方便易懂。但是在使用过程中感觉很繁琐,从建表到对表的增删改查等操作,如果表对象的属性很多,就需要使用大量的代码来执行建表、插入等。在代码执行中还需要对数据库和游标的进行及时关闭(开启使用,用完关闭),而且还需要部分sql语言,这在开发中产生bug进行调试时尤其不方便。

    目前android经常用的orm框架主要有greenDAO、OrmLite、AndrORM。 综合了网上的各种评价,greenDAO的运行效率最高,内存消耗最少,性能最佳。因此决定采用greenDAO框架,对项目的orm框架进行改进。

    greenDAO与ORMLite性能对比

    经过两天的修改,终于将项目里的数据库相关的都优化完了。在这过程中,发现greenDAO的性能确实不错,而且使用相当方便,不再需要涉及到任何的sql语言,可以直接通过对象类进行建表、增删改查等,尤其是api接口又方便易懂。在摸索学习中发现国内相关学习资料实在实在是太少,遂决定在此记录下自己对使用这个orm框架的一些心得和方法总结。

    一、greenDAO相关

    1.greenDAO官网:http://greendao-orm.com/

    2.项目下载地址:https://github.com/greenrobot/greenDAO(或者官网)

    greenDAO是一个可以帮助Android开发者快速将Java对象映射到SQLite数据库的表单中的ORM解决方案,通过使用一个简单的面向对象API,开发者可以对Java对象进行存储、更新、删除和查询。

    greenDAO的主要设计目标:

    *最大性能(最快的Android ORM)

    *易于使用API

    *高度优化

    *最小内存消耗

    二、使用步骤

    官方Demo里共有六个工程目录,分别为:

    (1).DaoCore:库目录,即jar文件greendao-1.3.0-beta-1.jar的代码;

    (2).DaoExample:android范例工程;

    (3).DaoExampleGenerator:DaoExample工程的DAO类构造器,java工程;

    (4).DaoGenerator:DAO类构造器,java工程;

    (5).DaoTest、PerformanceTestOrmLite:其他测试相关的工程。

    (一)DAO类构造

    首先需要新建一个java工程来生成DAO类文件,该工程需要导入greendao-generator.jar和freemarker.jar文件到项目中。

    01.package de.greenrobot.daogenerator.gentest;
    02.import de.greenrobot.daogenerator.DaoGenerator;
    03.import de.greenrobot.daogenerator.Entity;
    04.import de.greenrobot.daogenerator.Property;
    05.import de.greenrobot.daogenerator.Schema;
    06.import de.greenrobot.daogenerator.ToMany;
    07./**
    08.* Generates entities and DAOs for the example project DaoExample.
    09.*
    10.* Run it as a Java application (not Android).
    11.*
    12.* @author Markus
    13.*/
    14.public class ExampleDaoGenerator
    15.{
    16. 
    17.public static void main(String[] args) throws Exception
    18.{
    19.Schema schema = new Schema(3"de.greenrobot.daoexample");
    20. 
    21.addNote(schema);
    22.addCustomerOrder(schema);
    23. 
    24.new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
    25.}
    26. 
    27.private static void addNote(Schema schema)
    28.{
    29.Entity note = schema.addEntity("Note");
    30.note.addIdProperty();
    31.note.addStringProperty("text").notNull();
    32.note.addStringProperty("comment");
    33.note.addDateProperty("date");
    34.}
    35. 
    36.private static void addCustomerOrder(Schema schema)
    37.{
    38.Entity customer = schema.addEntity("Customer");
    39.customer.addIdProperty();
    40.customer.addStringProperty("name").notNull();
    41. 
    42.Entity order = schema.addEntity("Order");
    43.order.setTableName("ORDERS"); // "ORDER" is a reserved key<a href="http://www.it165.net/edu/ebg/" target="_blank" class="keylink">word</a>
    44.order.addIdProperty();
    45.Property orderDate = order.addDateProperty("date").getProperty();
    46.Property customerId = order.addLongProperty("customerId").notNull().getProperty();
    47.order.addToOne(customer, customerId);
    48. 
    49.ToMany customerToOrders = customer.addToMany(order, customerId);
    50.customerToOrders.setName("orders");
    51.customerToOrders.orderAsc(orderDate);
    52.}
    53. 
    54.}

    在main方法中,

    1.Schema schema = new Schema(3"de.greenrobot.daoexample");

    该方法第一个参数用来更新数据库版本号,第二个参数为要生成的DAO类所在包路径。

    然后进行建表和设置要生成DAO文件的目标工程的项目路径。

    addNote(schema);
    addCustomerOrder(schema);
    new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");

    其中src-gen这个目录名需要在运行前手动创建,否则会报错。

    如果运行后出现以下错误,则导入DaoGenerator项目的dao.ftl文件即可(或者直接使用DaoGenerator来生成DAO文件)。

    1.Exception in thread "main" java.io.FileNotFoundException: Template "dao.ftl" not found.
    2.at freemarker.template.Configuration.getTemplate(Configuration.java:742)
    3.at freemarker.template.Configuration.getTemplate(Configuration.java:665)
    4.at de.greenrobot.daogenerator.DaoGenerator.<init>(DaoGenerator.java:68)
    5.at de.greenrobot.daogenerator.gentest.ExampleDaoGenerator.main(ExampleDaoGenerator.java:41)

    运行后出现以下的提示说明DAO文件自动生成成功了,刷新一下DaoExample项目即可看到。

    01.greenDAO Generator
    02.Copyright 2011-2013 Markus Junginger, greenrobot.de. Licensed under GPL V3.
    03.This program comes with ABSOLUTELY NO WARRANTY
    04.Processing schema version 3...
    05.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\NoteDao.java
    06.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\Note.java
    07.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\CustomerDao.java
    08.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\Customer.java
    09.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\OrderDao.java
    10.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\Order.java
    11.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\DaoMaster.java
    12.Written F:\Android_Ex\work_10\DaoExample\src-gen\de\greenrobot\daoexample\DaoSession.java
    13.Processed 3 entities in 204ms

    运行后可以看到,DaoExample项目src-gen下面自动生成了8个文件,3个实体对象,3个dao,1个DaoMaster,1个DaoSession.

    (二)创建表

    1.创建一个实体类

    Entity note = schema.addEntity("Note");

    默认表名就是类名,也可以自定义表名

    1.dao.setTableName("NoteList");

    greenDAO会自动根据实体类属性创建表字段,并赋予默认值。例如在数据库方面的表名和列名都来源于实体类名和属性名。默认的数据库名称是大写使用下划线分隔单词,而不是在Java中使用的驼峰式大小写风格。例如,一个名为“CREATIONDATE”属性将成为一个数据库列“CREATION_DATE”。

    设置一个自增长ID列为主键:

    1.dao.addIdProperty().primaryKey().autoincrement();

    设置其他各种类型的属性:

    dao.addIntProperty("cityId");
    dao.addStringProperty("infoType").notNull();//非null字段
    dao.addDoubleProperty("Id");

    在生成的实体类中,int类型为自动转为long类型。

    如果在编译过程中出现以下错误,那么有可能是主键的类型错误所致:

    1.java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String

    在使用greenDAO时,一个实体类只能对应一个表,目前没法做到一个表对应多个实体类,或者多个表共用一种对象类型。后续的升级也不会针对这一点进行扩展。

    (二)表的增删改查

    增删改查相当方便,完全的面向对象,不需要涉及到任何的sql语言。

    1.查询

    范例1:查询某个表是否包含某个id:

    1.public boolean isSaved(int ID)
    2.{
    3.QueryBuilder<SaveList> qb = saveListDao.queryBuilder();
    4.qb.where(Properties.Id.eq(ID));
    5.qb.buildCount().count();
    6.return qb.buildCount().count() > 0 true false;
    7.}

    范例2:获取整个表的数据集合,一句代码就搞定!

    public List<PhotoGalleryDB> getPhotoGallery()
    {
    return photoGalleryDao.loadAll();// 获取图片相册
    }

    范例3:通过一个字段值查找对应的另一个字段值(为简便直接使用下面方法,也许有更简单的方法,尚未尝试)

    01./** 通过图片id查找其目录id */
    02.public int getTypeId(int picId)
    03.{
    04.QueryBuilder<PhotoGalleryDB> qb = photoGalleryDao.queryBuilder();
    05.qb.where(Properties.Id.eq(picId));
    06.if (qb.list().size() > 0)
    07.{
    08.return qb.list().get(0).getTypeId();
    09.}
    10.else
    11.{
    12.return -1;
    13.}
    14.}

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

    1.List joes = userDao.queryBuilder()
    2..where(Properties.FirstName.eq("Joe"))
    3..orderAsc(Properties.LastName)
    4..list();

    范例5:多重条件查询

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

    1.public List<CityInfoDB> getSupportingList(int cityId)
    2.{
    3.QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
    4.qb.where(qb.and(Properties.CityId.eq(cityId),Properties.InfoType.eq(HBContant.CITYINFO_SL)));
    5.qb.orderAsc(Properties.Id);// 排序依据
    6.return qb.list();
    7.}

    (2)获取firstname为“Joe”并且出生于1970年10月以后的所有user集合:

    1.QueryBuilder qb = userDao.queryBuilder();
    2.qb.where(Properties.FirstName.eq("Joe"),
    3.qb.or(Properties.YearOfBirth.gt(1970),
    4.qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));
    5.List youngJoes = qb.list();

    范例6:获取某列对象

    1.picJsonDao.loadByRowId(picId);

    2.增添/插入、修改

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

    1.public void addToPhotoTable(Photo p)
    2.{
    3.photoDao.insert(p);
    4.}

    插入时需要new一个新的对象,范例如下:

    1.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this"notes-db"null);
    2.db = helper.getWritableDatabase();
    3.daoMaster = new DaoMaster(db);
    4.daoSession = daoMaster.newSession();
    5.noteDao = daoSession.getNoteDao();
    6.Note note = new Note(null, noteText, comment, new Date());
    7.noteDao.insert(note);

    修改更新:

    1.photoDao.insertOrReplace(photo);
    2.photoDao.insertInTx(photo);

    3.删除:

    (1)清空表格数据

    1./** 清空相册图片列表的数据 */
    2.public void clearPhoto()
    3.{
    4.photoDao.deleteAll();
    5.}

    (2)删除某个对象

    1.public void deleteCityInfo(int cityId)
    2.{
    3.QueryBuilder<DBCityInfo> qb = cityInfoDao.queryBuilder();
    4.DeleteQuery<DBCityInfo> bd = qb.where(Properties.CityId.eq(cityId)).buildDelete();
    5.bd.executeDeleteWithoutDetachingEntities();
    6.}

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

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

    (三)常用方法笔记

    1.在Application实现得到DaoMaster和DaoSession的方法:

    01.private static DaoMaster daoMaster;
    02.private static DaoSession daoSession;
    03./**
    04.* 取得DaoMaster
    05.*
    06.* @param context
    07.* @return
    08.*/
    09.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.增删改查工具类:

    01.public class DBHelper
    02.{
    03.private static Context mContext;
    04.private static DBHelper instance;
    05. 
    06.private CityInfoDBDao cityInfoDao;
    07. 
    08.private DBHelper()
    09.{
    10.}
    11. 
    12.public static DBHelper getInstance(Context context)
    13.{
    14.if (instance == null)
    15.{
    16.instance = new DBHelper();
    17.if (mContext == null)
    18.{
    19.mContext = context;
    20.}
    21. 
    22.// 数据库对象
    23.DaoSession daoSession = HBApplication.getDaoSession(mContext);
    24.instance.cityInfoDao = daoSession.getCityInfoDBDao();
    25.}
    26.return instance;
    27.}
    28. 
    29./** 添加数据 */
    30.public void addToCityInfoTable(CityInfo item)
    31.{
    32.cityInfoDao.insert(item);
    33.}
    34. 
    35./** 查询 */
    36.public List<EstateLoveListJson> getCityInfoList()
    37.{
    38.QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
    39.return qb.list();
    40.}
    41. 
    42./** 查询 */
    43.public List<CityInfo> getCityInfo()
    44.{
    45.return cityInfoDao.loadAll();// 查找图片相册
    46.}
    47. 
    48./** 查询 */
    49.public boolean isSaved(int Id)
    50.{
    51.QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
    52.qb.where(Properties.Id.eq(Id));
    53.qb.buildCount().count();
    54.return qb.buildCount().count() > 0 true false;// 查找收藏表
    55.}
    56. 
    57./** 删除 */
    58.public void deleteCityInfoList(int Id)
    59.{
    60.QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
    61.DeleteQuery<CityInfo> bd = qb.where(Properties.Id.eq(Id)).buildDelete();
    62.bd.executeDeleteWithoutDetachingEntities();
    63.}
    64. 
    65./** 删除 */
    66.public void clearCityInfo()
    67.{
    68.cityInfoDao.deleteAll();
    69.}
    70. 
    71./** 通过城市id查找其类型id */
    72.public int getTypeId(int cityId)
    73.{
    74.QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
    75.qb.where(Properties.Id.eq(cityId));
    76.if (qb.list().size() > 0)
    77.{
    78.return qb.list().get(0).getTypeId();
    79.}
    80.else
    81.{
    82.return 0;
    83.}
    84.}
    85. 
    86./** 多重查询 */
    87.public List<CityInfo> getIphRegionList(int cityId)
    88.{
    89.QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
    90.qb.where(qb.and(Properties.CityId.eq(cityId), Properties.InfoType.eq(HBContant.CITYINFO_IR)));
    91.qb.orderAsc(Properties.Id);// 排序依据
    92.return qb.list();
    93.}
    94.}

    另外,还有多表关联、惰性加载等功能,待后续研究。

    参考资料:

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

    2.http://greendao-orm.com/documentation/how-to-get-started/

    3.http://blog.csdn.net/krislight/article/details/9391455

Android 数据库ORM框架GreenDao学习心得及使用总结<一>的更多相关文章

  1. Android 数据库ORM框架GreenDao学习心得及使用总结<二>

    转:http://blog.csdn.net/xushuaic/article/details/24496191 第五篇 查询 查询会返回符合某些特定标准的实体.你可以使用原始的SQL定制查询语句,或 ...

  2. 【转载】Android开源:数据库ORM框架GreenDao学习心得及使用总结

    转载链接:http://www.it165.net/pro/html/201401/9026.html 最近在对开发项目的性能进行优化.由于项目里涉及了大量的缓存处理和数据库运用,需要对数据库进行频繁 ...

  3. 数据库ORM框架GreenDao

    常用的数据库: 1). Sql Server2). Access3). Oracle4). Sysbase5). MySql6). Informix7). FoxPro8). PostgreSQL9) ...

  4. Android SQLite ORM框架greenDAO在Android Studio中的配置与使用

    博客: 安卓之家 微博: 追风917 CSDN: 蒋朋的家 简书: 追风917 博客园: 追风917 # 说明 greenDAO是安卓中处理SQLite数据库的一个开源的库,详情见其官网:我是官网 详 ...

  5. 数据库开源框架GreenDao的使用解析

    数据库开源框架GreenDao的使用解析 1,GreenDao概述 1),greenDao是一个当下十分火热的数据库开源框架,或者说是一个帮助Android开发者将数据存到SQLite中的一个开源项目 ...

  6. ORM框架--GreenDao 3.0基本使用指南

    0. ORM框架--GreenDao 3.0基本使用指南 1. Gradle 的配置 这里可以参照官方的文档进行最新的配置(本示例的版本等你看到可能就不是最新的了),但是值得注意的一点是,GreenD ...

  7. ORM框架greenDao 2 (用于了解旧版本的使用方法,目前最新版本为3.2.2,使用注释的方式来生成)

    摘要: Android中对SQLite数据库使用,是一件非常频繁的事情.现今,也有非常多的SQLite处理的开源框架,其中最著名的greenDao,它以占用资源少,处理效率高等特点,成为优秀的ORM框 ...

  8. LitepalNewDemo【开源数据库ORM框架-LitePal2.0.0版本的使用】

    版权声明:本文为HaiyuKing原创文章,转载请注明出处! 前言 本Demo使用的是LitePal2.0.0版本,对于旧项目如何升级到2.0.0版本,请阅读<赶快使用LitePal 2.0版本 ...

  9. [Android]Android端ORM框架——RapidORM(v2.1)

    以下内容为原创,欢迎转载,转载请注明 来自天天博客:http://www.cnblogs.com/tiantianbyconan/p/6020412.html [Android]Android端ORM ...

随机推荐

  1. Sublime Text 3 无法使用package control安装插件解决办法

    Crossing's Blog NOT Genius but Try Best 首页 分类 关于 归档 标签 问题貌似出现在liveStyle版本更新之后,因为打算安装javascript next和 ...

  2. 总结一下.net framework适合装在哪些系统中

    最近在客户这部署,环境是windows server2003 service pack2.因为vs2012开发环境是.net framework4.5,所以发布iis的时候,尝试在sever2003上 ...

  3. 02Android用户界面优化之(一)Android Fragment

    一.使用Fragment 1.AndroidManifest.xml文件 <?xml version="1.0" encoding="utf-8"?> ...

  4. oracle中set define off

    set define off关闭替代变量功能 在SQL*Plus中默认的"&"表示替代变量,也就是说,只要在命令中出现该符号,SQL*Plus就会要你输入替代值.这就意味着 ...

  5. codevs1304 拓扑序计数

    题目描述                     Description 求一颗有根树/树形图的拓扑序个数. 输入描述                 Input Description        ...

  6. Android Fragment真正意义上的onResume和onPause

    Fragment虽然有onResume和onPause的,但是这两个方法是Activity的方法,调用时机也是与Activity相同,和ViewPager搭配使用这个方法就很鸡肋了,根本不是你想要的效 ...

  7. xml drawable

    1.Shape drawable:改变组件的形状和渐变xml shape标签 corner标签:改变轮廓 gradient:颜色填充的渐变 android:angle  android:angle=“ ...

  8. [转]用Gson来解析Json数据

    转自太阳尚远的博客:http://blog.yeqianfeng.me/2016/03/02/use_gson_to_parse_json/ 在我们实际开发中像Json和XML这两种格式的数据是最常见 ...

  9. 5路数字量输入Di,5路大电流继电器输出,可电脑控制,支持modbus协议工业模块,支持和DCS,PLC无缝对接。

    数字量输入输出模块MRD-5060具有5路DI,5路继电器输出,1路485接口(支持Modbus RTU),能实现5路DI(干接点输入)转485的采集,也可以通过485控制5路继电器(5A30VDC, ...

  10. 限制TextBox输入,只能输入Double类型数字

    public class TextBoxDouble : TextBox { public TextBoxDouble() { KeyDown += TextBoxDouble_KeyDown; Te ...