GreenDao是将原始的SQL语句封装起来,极大地简化了对数据库相关操作,据了解它比其他的数据库相关的框架性能要好,扩张性、速度等都很强。
使用:1.在主项目app中进行依赖:compile 'de.greenrobot:greendao:2.1.0'
2.创建JavaMidule,并且在JavaModule中依赖:compile 'de.greenrobot:greendao-generator:2.1.0'
3.在Java类中进行表的创建:
public class MyClass {
public static void main(String[] arg){
Schema schema=new Schema(1,"www.asendi.com");
/**
* 创建表
*/
Entity son=schema.addEntity("Son");
son.addStringProperty("name");
son.addIntProperty("age");
son.addIdProperty();
Property fatherId=son.addLongProperty("fatherId").getProperty();
Entity father=schema.addEntity("Father");
father.addIdProperty();
father.addStringProperty("name");
father.addIntProperty("age");
son.addToOne(father,fatherId);
try {
new DaoGenerator().generateAll(schema,"app/src/main/java");
} catch (Exception e) {
e.printStackTrace();
}
}
}
然后运行该Java类,运行成功后在主项目的app-src-main-java下会多了一个包,包名即最开始Schema对象传入的第二个参数。以上代码就创建了Son表和Father表,
Son表中的属性为:name、age、_id,
Father表中的属性为name、age、_id,
并且Son表中引用Father表中的_id作为外键
进行Dao层的实例和创建数据库:
private void openDb(){
db=new DaoMaster.DevOpenHelper(this,"person.db",null).getWritableDatabase();
mDaoMaster=new DaoMaster(db);
mSession=mDaoMaster.newSession();
mSonDao=mSession.getSonDao();
mFatherDao=mSession.getFatherDao();
}
4.插入数据:
接着上面:
private void addPerson() {
Son son = new Son();
son.setName("tomkin");
son.setAge(19);
Father father = new Father();
father.setName("tFather");
father.setAge(43);
long fatherId = mFatherDao.insert(father);
son.setFatherId(fatherId);
mSonDao.insert(son);
}
5.在android中进行查询:
查询所有:List<Son>list=mSonDao.queryBuilder().listLazy();//.list()
按属性查询:Son nate=mSonDao.queryBuilder().where(SonDao.Properties.Name.eq("senddi")).unique();
匹配符查询:List tomkin=mSonDao.queryBuilder().where(SonDao.Properties.Name.like("tomkin% ")).list();
范围(区间)查询:List sons=mSonDao.queryBuilder().where(SonDao.Properties.Age.between(20,30)).list();
范围(大于)查询:List data=mSonDao.queryBuilder().where(SonDao.Properties.Age.gt(18)).list();
范围(小于)查询:List data=mSonDao.queryBuilder().where(SonDao.Properties.Age.lt(19)).list();
范围(不等于)查询:List data=mSonDao.queryBuilder().where(SonDao.Properties.Age.notEq(19)).list();
范围(大于等于)查询:List data=mSonDao.queryBuilder().where(SonDao.Properties.Age.ge(19)).list();
升序查询:List<Son> data=mSonDao.queryBuilder().orderAsc(SonDao.Properties.Age).list();
降序查询:List<Son> data=mSonDao.queryBuilder().orderDesc(SonDao.Properties.Age).list();
与原始的SQL语句结合:(年龄在45岁一下的父亲的ID)
List data=mSonDao.queryBuilder().where(
new WhereCondition.StringCondition("FATHER_UD IN" +
"(SELECT _ID FROM FATHER WHERE AGE<45)")).list();
6.多线程的查询:
当前线程的Query对象要放在创建该对象的线程中去,否则会抛出异常
使用的方法为:query.forCurrentThread(); (要注意)
forCurrentThread();
源码:(AbstractQueryData<T, Q extends AbstractQuery<T>>中的forCurrentThread())
Q forCurrentThread(Q query) {
if (Thread.currentThread() == query.ownerThread) {
System.arraycopy(initialValues, 0, query.parameters, 0, initialValues.length);
return query;
} else {
return forCurrentThread();
}
}
首先是拿到当前线程的ID,拿到后进行一系列的判断,最后的判断是如果是本线程的ID,那么将Query的查询参数拷贝到数组中去,否则执行下面的forCurrentThread()
Q forCurrentThread() {
int threadId = Process.myTid();
if (threadId == 0) {
// Workaround for Robolectric, always returns 0
long id = Thread.currentThread().getId();
if (id < 0 || id > Integer.MAX_VALUE) {
throw new RuntimeException("Cannot handle thread ID: " + id);
}
threadId = (int) id;
}
synchronized (queriesForThreads) {
WeakReference<Q> queryRef = queriesForThreads.get(threadId);
Q query = queryRef != null ? queryRef.get() : null;
if (query == null) {
gc();
query = createQuery();
queriesForThreads.put(threadId, new WeakReference<Q>(query));
} else {
System.arraycopy(initialValues, 0, query.parameters, 0, initialValues.length);
}
return query;
}
}
上面这个forCurrentThread()首先拿到线程的id,然后拿到WeakReference<Q> queryRef,进而判断 queryRef是否为空,如果不为空,那么query则等于query.get();如果为null,则执行gc();然后创建query对象并把该对象放在集合中去
checkThread():检查线程
gc()方法源码:
void gc() {
synchronized (queriesForThreads) {
for (int i = queriesForThreads.size() - 1; i >= 0; i--) {
if (queriesForThreads.valueAt(i).get() == null) {
queriesForThreads.remove(queriesForThreads.keyAt(i));
}
}
}
}
该方法是遍历查询线程的集合,然后把查询的对象移除。
源码:
protected void checkThread() {
if (Thread.currentThread() != ownerThread) {
throw new DaoException(
"Method may be called only in owner thread, use forCurrentThread to get an instance for this thread");
}
}
该方法检查了是否运行在自己的线程上,否则抛异常;
7.一对多的查询方式:(数据一次性查询出来,不会对UI线程造成阻塞)
如果想要一对多的关系,则在Java代码中需要进行修改:
Schema schema=new Schema(1,"www.asendi.com");
/**
* 创建表
*/
Entity son=schema.addEntity("Son");
son.addStringProperty("name");
son.addIntProperty("age");
son.addIdProperty();
// Property fatherId=son.addLongProperty("fatherUd").getProperty();
Entity father=schema.addEntity("Father");
father.addIdProperty();
father.addStringProperty("name");
father.addIntProperty("age");
Property sonId=father.addLongProperty("sonId").getProperty();
father.addToOne(son,sonId);
son.addToMany(father,sonId).setName("fathers");
try {
new DaoGenerator().generateAll(schema,"app/src/main/java");
} catch (Exception e) {
e.printStackTrace();
}
(注意加粗的代码)。