GreenDao的进阶
在上一篇的greendao的使用的介绍中,我们知道了利用XXXDao可以完成数据库的一些基础的操作,例如:增、删、改、查
再次回忆三个自动生成的核心类:DaoMaster、DaoSession、XXXDao
- DaoMaster称作会话层,DaoMaster包含了一个DevOpenHelper(继承自OpenHelper),DevOpenHelper包含了对数据库的基础操作,例如:创建表,删除表,更新表,值得一提的是,DevOpenHelper类当中的升级数据库的方式是先将所有的表格删除,然后在重新创建表格,所有的数据就会消失掉,解决这个办法请参考:greendao3.0以上使用步骤(二):数据库到底该怎么升级http://blog.csdn.net/huangxiaoguo1/article/details/54574713
- DaoSession 管理XXXDao.class类,也提供了增删改查的方法(其实是使用了AbstractDao抽象类)
- XXXDao 每一个table实体(Entity)对应的Dao类,提供了数据的增删改查等等一系列操作,比DaoSession类提供的方法更加具体
在项目中使用GreenDao操作数据的步骤:
1. (推荐)自己维护一个DaoManager的类,用来获取DaoMaster和DaoSession实例,例如:
public class DaoManager {
//数据库名
private static final String DB_NAME = "student.db";
private Context mContext;
//单例模式
private volatile static DaoManager mDaoManager;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
private DaoMaster.DevOpenHelper mOpenHelper;
private DaoManager(Context context) {
this.mContext = context;
}
public static DaoManager getInstance(Context context) {
if (mDaoManager == null) {
synchronized (DaoManager.class) {
mDaoManager = new DaoManager(context);
}
}
return mDaoManager;
}
/**
* 判断是否存在数据库,如果不存在,就创建数据库
*
* @return
*/
public DaoMaster getDaoMaster() {
if (mDaoMaster == null) {
mOpenHelper = new DaoMaster.DevOpenHelper(mContext, DB_NAME);
//完成数据库的创建
mDaoMaster = new DaoMaster(mOpenHelper.getWritableDatabase());
}
return mDaoMaster;
}
public DaoSession getDaoSession() {
if (mDaoSession == null) {
if (mDaoMaster == null) {
mDaoMaster = getDaoMaster();
}
mDaoSession = mDaoMaster.newSession();
}
return mDaoSession;
}
/**
* 打开输出日志的操作,默认是关闭的
*/
public void setDebug() {
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
/**
* 关闭
*/
public void closeDaoSession() {
if (mDaoSession != null) {
mDaoSession.clear();
mDaoSession = null;
}
}
public void closeHelper() {
if (mOpenHelper != null) {
mOpenHelper.close();
mOpenHelper = null;
}
}
/**
* 关闭数据库连接
*/
public void closeDBConncetion() {
closeDaoSession();
closeHelper();
}
}
2. 创建每一张table表格对应的dao,如下
public class StudentDaoManager {
private DaoManager mDaoManager;
private StudentDaoManager(Context context) {
mDaoManager = DaoManager.getInstance(context);
}
//单例模式
private static volatile StudentDaoManager mStudentDaoManager;
public static StudentDaoManager getInstance(Context context) {
if (mStudentDaoManager == null) {
synchronized (StudentDaoManager.class) {
if (mStudentDaoManager == null) {
mStudentDaoManager = new StudentDaoManager(context);
}
}
}
return mStudentDaoManager;
}
/**
* 插入单条数据
*
* @param student 需要插入的数据
* @return 是否插入成功
*/
public boolean insertStu(Student student) {
boolean flag = false;
flag = mDaoManager.getDaoSession().getStudentDao().insert(student) != -1 ? true : false;
return flag;
}
/**
* 插入或者更新单条数据,如果数据已经存在,那么更新该条数据
*
* @param student
* @return 是否插入成功
*/
public boolean insertOrReplace(Student student) {
boolean flag = false;
flag = mDaoManager.getDaoSession().getStudentDao().insertOrReplace(student) != -1 ? true : false;
return flag;
}
/**
* 插入多条数据
*
* @param isUseTra 是否使用事物
* @param list 需要批量插入的数据的列表
* @return 是否插入成功
*/
public boolean insertMutiStus(boolean isUseTra, List<Student> list) {
boolean flag = false;
try {
if (isUseTra) {
//使用事物批量插入
mDaoManager.getDaoSession().getStudentDao().insertOrReplaceInTx(list);
} else {
for (Student student : list) {
//使用普通的方法,单条单条的插入
mDaoManager.getDaoSession().getStudentDao().insertOrReplace(student);
}
}
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除单条数据
*
* @param student
* @return 是否插入成功
*/
public boolean delete(Student student) {
boolean flag = false;
try {
mDaoManager.getDaoSession().getStudentDao().delete(student);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 更新数据
*
* @param student 需要更新的数据
* @return 是否插入成功
*/
public boolean update(Student student) {
boolean flag = false;
try {
mDaoManager.getDaoSession().getStudentDao().update(student);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 返回所有的数据
*
* @return 列表
*/
public List<Student> queryAll() {
List<Student> students = mDaoManager.getDaoSession().getStudentDao().loadAll();
return students;
}
/**
* 返回单条记录
*
* @param studentId Student对象的ID,主键
* @return 单条记录
*/
public Student queryOne(long studentId) {
return mDaoManager.getDaoSession().getStudentDao().load(studentId);
}
/**
* 分页查询
*
* @param limit 查询记录的条数
* @param offset 查询的起始位置
* @return
*/
public List<Student> queryOffset(int limit, int offset) {
QueryBuilder<Student> builder = mDaoManager.getDaoSession().getStudentDao().queryBuilder();
builder.offset(offset).limit(limit);
List<Student> list = builder.list();
return list;
}
/**
* 使用QueryBuilder进行查询,
*
* @return
*/
public List<Student> queryWithBuilder() {
QueryBuilder<Student> builder = mDaoManager.getDaoSession().getStudentDao().queryBuilder();
//1.使用了where(所有的where之间都是逻辑与的关系,相当于and)相当于:select * from student where name like "%乐" and sex = "男";
builder.where(StudentDao.Properties.Name.like("%乐")).where(StudentDao.Properties.Sex.eq("男"));
//2.上面相当于:
// builder.where(StudentDao.Properties.Name.like("%乐"),StudentDao.Properties.Sex.eq("男"));
//3.逻辑或,相当于or,将许多个查询条件串联起来
builder.whereOr(StudentDao.Properties.Name.like("%乐%"), StudentDao.Properties.Sex.eq("男"));
//4.和1中的查询结果是一样的
List<Student> students = mDaoManager.getDaoSession().getStudentDao().queryRaw("where name like ? and sex = ?", new String[]{"%乐%", "男"});
List<Student> studentList = builder.list();
return students;
}
}
上面的代码有些长,需要注意的是:
1.使用事务将数据插入(insert)到数据库的时候,对于数据量比较大的应该采取开启事务
//使用事物批量插入
mDaoManager.getDaoSession().getStudentDao().insertOrReplaceInTx(list);
可以看到直接传入一个List对象即可.另外需要注意的是,在批量插入数据的过程中,如果出现一个数据插入错误,那么事务就会回滚到插入前的状态.事务的开启与关闭,在greendao中已经为我们封装好了,我们不用操心.
2.查询数据是重中之重,对于SQL不是很熟悉的程序员来说,QueryBuilder是个好东西,先来看看怎么用吧:
QueryBuilder<Student> builder = mDaoManager.getDaoSession().getStudentDao().queryBuilder();
//1.使用了where(所有的where之间都是逻辑与的关系,相当于and)相当于:select * from student where name like "%乐" and sex = "男";
builder.where(StudentDao.Properties.Name.like("%乐")).where(StudentDao.Properties.Sex.eq("男"));
//2.上面相当于:
// builder.where(StudentDao.Properties.Name.like("%乐"),StudentDao.Properties.Sex.eq("男"));
//3.逻辑或,相当于or,将许多个查询条件串联起来
builder.whereOr(StudentDao.Properties.Name.like("%乐%"), StudentDao.Properties.Sex.eq("男"));
//4.和1中的查询结果是一样的
List<Student> students = mDaoManager.getDaoSession().getStudentDao().queryRaw("where name like ? and sex = ?", new String[]{"%乐%", "男"});
3. 我们知道XXXDao是继承自AbstractDao的,XXXDao封装了基本的增删改查的方法,而DaoSession也包含基本的增删改查的方法,在维护自己的XXXDao的时候,就像上面的示例代码中我自己定义了一个StudentDaoManager,里面包含了许多的增删改查的方法,这个StudentDaoManager只针对一张table,也就是Student,而日常的开发中数据库中肯定有多张表格,我们针对一张表格就写一个DaoManager这岂不是增加了开发的重复性.因此我建议直接将XXXDao这个自动生成的忽略掉,直接用DaoSession中的增删改查方法来操作数据库数据,示例如下:
//插入数据,T是泛型
public void insert(T t) {
mDaoManager.getDaoSession().insert(t);
}
这样此数据库中的所有表格对应的数据就都能使用此方法了,而不用一个Entity就需要维护一个Dao
**4.**Properties是Student是StudentDao的一个内部类,维护了每一个table实体的列名
关于更多类似于where、whereOr、like等等的greendao关键词的含义,请参考greendao官方API(http://greenrobot.org/files/greendao/javadoc/current/)