对GreenDao的使用

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();
        }
(注意加粗的代码)。




  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值