标签:
greendao’的主要设计目标
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;
/**
* @description:
使用说明:
0.android工程导入dist/greendao-xxx.jar
1.用实体生成demo,生成相应的实体及其数据库操作类
2.(可选)对上述数据库操作类进行service层的封装
3.修改DaoMaster中数据库名称及debug等参数
4.最好单例化DaoMaster,并在application中进行初始化
5.(在通过service中)创建DaoSession,获取相应dao进行实体的数据库相关操作
6.参考链接(异或百度)
官网http://greendao-orm.com/
源码https://github.com/greenrobot/greenDAO
更新说明
2014-10-31
DaoCore android工程源码
DaoExample android工程demo
DaoExampleGenerator 实体生成demo
DaoGenerator 实体生成器源码
* @author samy
* @date 2015-4-27 下午5:28:22
*/
public class ExampleDaoGenerator {
// (1)创建Java工程
// (2)导入greenDao-generator.jar和freemarker.jar两个包。
// freemarker是一个用java写的模板引擎,它能够基于模板来生成文本输出。应该就是用来自动生成DAO文件的。
/**
* @description:(3)创建schema
* @author samy
* @date 2015年6月15日 下午4:29:11
*/
public static void main(String[] args) throws Exception {
// 创建schema时需要制定数据库的版本号、默认的Java package等参数。
Schema schema = new Schema(1001, "com.zsy.sample.support.db.onepiececategory");
// 默认Java package用来存放生成的entity、DAO文件、test代码。但也可以重新制定test文件的单独路径以及DAO文件的路径,代码:
// schema.setDefaultJavaPackageTest("de.greenrobot.daoexample.test");
// schema.setDefaultJavaPackageDao("de.greenrobot.daoexample.dao");
// 另外,还有两个flag,用来标示entity是否是activie以及是否使用keep sections。代码:
schema.enableKeepSectionsByDefault();
// schema2.enableActiveEntitiesByDefault();
// Keep sections:因为entity class在每次generator执行时均会覆盖原来的程序,为了能够添加用户自定义代码到entity中,需要设置该参数。只需要把自己的代码添加到下面的KEEP[]块中间就可以了。
// KEEP INCLUDES - put your custom includes here
// KEEP INCLUDES END
// ...
// KEEP FIELDS - put your custom fields here
// KEEP FIELDS END
// ...
// KEEP METHODS - put your custom methods here
// KEEP METHODS END
addProductCategory(schema);
// addCustomerOrder(schema);
/**
*(5)生成DAO文件 生成DAO文件就是使用main函数的最后一句话,其中后面的参数就是希望自动生成的代码对应的项目路径。
* 注:设置的路径必须存在,否则会抛出异常。该路径是另外的工程下面的目录,当然也可以自己不这么做,只要这个目录存在就行。在schema创建的时候指定的package接口也是相对于该路径的。
*/
new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
}
private static void addProductCategory(Schema schema) {
Entity note = schema.addEntity("OnePieceCategory");
note.addIdProperty();
note.addStringProperty("typeId");
note.addStringProperty("typeName");
note.addStringProperty("typeImage");
note.addIntProperty("levelNum");
note.addIntProperty("orderBy");
note.addStringProperty("parentId");
note.addStringProperty("webTypeImage");
}
private static void addNote(Schema schema) {
Entity note = schema.addEntity("OncePieceCategory");
note.addIdProperty();
note.addStringProperty("typeId");
note.addStringProperty("typeName");
note.addStringProperty("parentId");
}
/**
* @description:(4)创建entity
* schema中可以添加entity,简单的理解应该是entity对应一个具体的java class,entity可以添加property。Entity通常也是对应一个table。
* 除了添加property之外,entity也可以添加to-one和to-many关系,即添加一对一的关系和一对多的关系。
* @author samy
* @date 2015年6月15日 下午4:28:51
*/
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);
}
}
查询:
(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(1, 1977);
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进行数据库的增删改查时及其方便,而且性能极佳。
private static DaoMaster daoMaster;
private static DaoSession daoSession;
/**
* 取得DaoMaster
*
* @param context
* @return
*/
public static DaoMaster getDaoMaster(Context context)
{
if (daoMaster == null)
{
OpenHelper helper = new DaoMaster.DevOpenHelper(context, HBContant.DATABASE_NAME, null);
daoMaster = new DaoMaster(helper.getWritableDatabase());
}
return daoMaster;
}
/**
* 取得DaoSession
*
* @param context
* @return
*/
public static DaoSession getDaoSession(Context context)
{
if (daoSession == null)
{
if (daoMaster == null)
{
daoMaster = getDaoMaster(context);
}
daoSession = daoMaster.newSession();
}
return daoSession;
}
public class DBHelper
{
private static Context mContext;
private static DBHelper instance;
private CityInfoDBDao cityInfoDao;
private DBHelper()
{
}
public static DBHelper getInstance(Context context)
{
if (instance == null)
{
instance = new DBHelper();
if (mContext == null)
{
mContext = context;
}
// 数据库对象
DaoSession daoSession = HBApplication.getDaoSession(mContext);
instance.cityInfoDao = daoSession.getCityInfoDBDao();
}
return instance;
}
/** 添加数据 */
public void addToCityInfoTable(CityInfo item)
{
cityInfoDao.insert(item);
}
/** 查询 */
public List<EstateLoveListJson> getCityInfoList()
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
return qb.list();
}
/** 查询 */
public List<CityInfo> getCityInfo()
{
return cityInfoDao.loadAll();// 查找图片相册
}
/** 查询 */
public boolean isSaved(int Id)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
qb.where(Properties.Id.eq(Id));
qb.buildCount().count();
return qb.buildCount().count() > 0 ? true : false;// 查找收藏表
}
/** 删除 */
public void deleteCityInfoList(int Id)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
DeleteQuery<CityInfo> bd = qb.where(Properties.Id.eq(Id)).buildDelete();
bd.executeDeleteWithoutDetachingEntities();
}
/** 删除 */
public void clearCityInfo()
{
cityInfoDao.deleteAll();
}
/** 通过城市id查找其类型id */
public int getTypeId(int cityId)
{
QueryBuilder<CityInfo> qb = cityInfoDao.queryBuilder();
qb.where(Properties.Id.eq(cityId));
if (qb.list().size() > 0)
{
return qb.list().get(0).getTypeId();
}
else
{
return 0;
}
}
/** 多重查询 */
public List<CityInfo> getIphRegionList(int cityId)
{
QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();
qb.where(qb.and(Properties.CityId.eq(cityId), Properties.InfoType.eq(HBContant.CITYINFO_IR)));
qb.orderAsc(Properties.Id);// 排序依据
return qb.list();
}
}
对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
标签:
原文地址:http://www.cnblogs.com/hongfeiliuxing/p/4580806.html