GreenDao学习笔记——初始化和增删改查
2016-01-24 18:40
288 查看
GreenDao的初始化:
这个代码主要是用于建立数据库和初始化一些变量,如初始化NoteDao的父类AbstractDao的变量和参数,
其中:
SQLiteDatabase db:我们建立的数据库对象;
DaoConfig config:用于保存数据访问对象Dao的基本数据;
TableStatements statements:用于生成操作数据表的SQL statements;
identityScope:greendao有一个缓存机制,即把用户插入,更改或查找的实体保存在内存中,当用户下一次查找时先从内存中查找,如果不存在再从数据库中查找,当表的主键是数字类型的时候,identityScopeLong将不会空,并且指向identityScope。
在初始每个dao对象的DaoConfig的时候,判断主键是否是数字类型,
如果主键是数字类型的话,initIdentityScope时identityScope 初始化IdentityScopeLong类型,
然后在数据操作对象的父类的构造方法中,将identityScopeLong 指向identityScope,
然后,所有主键为数字类型dao对象获取内存中缓存对象的都会调用IdentityScopeLong中的get方法,
所以,如果主键不是long类型的话就会报类型转换错误!
错误的贴图。。。。
当然,我们可以自己控制是否使用缓存功能,在DaoMaster中有两个初始化DaoSession的方法,
我们可以使用第二个构造方法并传入type为IdentityScopeType.None,这样initIdentityScope方法就会包identityScope 赋为空值,即不使用缓存机制。
在使用greendao缓存机制的情况下,如果数据表的主键是数字类型的话,一定要使用long类型,不然不会报类型转换错误
插入对象insert:
greendao在底层的实现是:
首先判断数据库是否被当前线程锁住,如果是,绑定参数并执行插入,如果不是,则开启一个事务,然后绑定参数并执行插入。
其中,NoteDao重写了父类AbstractDao的bindValues方法,进行相对应对象数据的绑定,
删除对象delete:
底层源码的实现是:
删除对象与插入对象相似,删除操作目前仅支持操作单一主键的表,
判断是否使用缓存机制,是的话删除缓存中的实体。
修改对象update:
底层源码的实现是:
同样,
查找对象Search:
greendao提供提供多种查找方式进行查找。
查找对象的实现实现是原理是传入多个限制条件,然后在底层代码中拼接sql查询语句进行查询,然后在转换成相对应的对象。查询的机制跟其他操作方式一样,如果有使用greendao的缓存机制,则先从缓存中获取,再从数据库获取,如果没有使用缓存机制,则直接从数据库中获取。
如果需要使用更复杂的查询方法的话,可以查看Property类和QueryBuilder的源码,greendao提供多种方式的拼接,可以组成日常开发中经常用到的查询语句。
需要一提的是greendao的懒加载功能:
参考资料:
http://greenrobot.org/
http://blog.csdn.net/xushuaic/article/details/24434881
http://blog.csdn.net/xushuaic/article/details/24438841
http://blog.csdn.net/xushuaic/article/details/24496191
DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null); db = helper.getWritableDatabase(); daoMaster = new DaoMaster(db); daoSession = daoMaster.newSession(); noteDao = daoSession.getNoteDao();
这个代码主要是用于建立数据库和初始化一些变量,如初始化NoteDao的父类AbstractDao的变量和参数,
protected final SQLiteDatabase db; protected final DaoConfig config; protected IdentityScope<K, T> identityScope; protected IdentityScopeLong<T> identityScopeLong; protected TableStatements statements; protected final AbstractDaoSession session; protected final int pkOrdinal;
其中:
SQLiteDatabase db:我们建立的数据库对象;
DaoConfig config:用于保存数据访问对象Dao的基本数据;
TableStatements statements:用于生成操作数据表的SQL statements;
identityScope:greendao有一个缓存机制,即把用户插入,更改或查找的实体保存在内存中,当用户下一次查找时先从内存中查找,如果不存在再从数据库中查找,当表的主键是数字类型的时候,identityScopeLong将不会空,并且指向identityScope。
在初始每个dao对象的DaoConfig的时候,判断主键是否是数字类型,
if (pkProperty != null) { Class<?> type = pkProperty.type; keyIsNumeric = type.equals(long.class) || type.equals(Long.class) || type.equals(int.class) || type.equals(Integer.class) || type.equals(short.class) || type.equals(Short.class) || type.equals(byte.class) || type.equals(Byte.class); } else { keyIsNumeric = false; }
如果主键是数字类型的话,initIdentityScope时identityScope 初始化IdentityScopeLong类型,
public void initIdentityScope(IdentityScopeType type) { if (type == IdentityScopeType.None) { identityScope = null; } else if (type == IdentityScopeType.Session) { if (keyIsNumeric) { identityScope = new IdentityScopeLong(); } else { identityScope = new IdentityScopeObject(); } } else { throw new IllegalArgumentException("Unsupported type: " + type); } }
然后在数据操作对象的父类的构造方法中,将identityScopeLong 指向identityScope,
public AbstractDao(DaoConfig config, AbstractDaoSession daoSession) { this.config = config; this.session = daoSession; db = config.db; identityScope = (IdentityScope<K, T>) config.getIdentityScope(); if (identityScope instanceof IdentityScopeLong) { identityScopeLong = (IdentityScopeLong<T>) identityScope; } statements = config.statements; pkOrdinal = config.pkProperty != null ? config.pkProperty.ordinal : -1; }
然后,所有主键为数字类型dao对象获取内存中缓存对象的都会调用IdentityScopeLong中的get方法,
public T get(Long key) { return get2(key); }
所以,如果主键不是long类型的话就会报类型转换错误!
错误的贴图。。。。
当然,我们可以自己控制是否使用缓存功能,在DaoMaster中有两个初始化DaoSession的方法,
public DaoSession newSession() { return new DaoSession(db, IdentityScopeType.Session, daoConfigMap); } public DaoSession newSession(IdentityScopeType type) { return new DaoSession(db, type, daoConfigMap); }
我们可以使用第二个构造方法并传入type为IdentityScopeType.None,这样initIdentityScope方法就会包identityScope 赋为空值,即不使用缓存机制。
public void initIdentityScope(IdentityScopeType type) { if (type == IdentityScopeType.None) { identityScope = null; } else if (type == IdentityScopeType.Session) { if (keyIsNumeric) { identityScope = new IdentityScopeLong(); } else { identityScope = new IdentityScopeObject(); } } else { throw new IllegalArgumentException("Unsupported type: " + type); } }
在使用greendao缓存机制的情况下,如果数据表的主键是数字类型的话,一定要使用long类型,不然不会报类型转换错误
插入对象insert:
Note note = new Note(null, noteText, comment, new Date()); getNoteDao().insert(note);
greendao在底层的实现是:
private long executeInsert(T entity, SQLiteStatement stmt) { long rowId; if (db.isDbLockedByCurrentThread()) { synchronized (stmt) { bindValues(stmt, entity); rowId = stmt.executeInsert(); } } else { // Do TX to acquire a connection before locking the stmt to avoid deadlocks db.beginTransaction(); try { synchronized (stmt) { bindValues(stmt, entity); rowId = stmt.executeInsert(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); } } updateKeyAfterInsertAndAttach(entity, rowId, true); return rowId; }
首先判断数据库是否被当前线程锁住,如果是,绑定参数并执行插入,如果不是,则开启一个事务,然后绑定参数并执行插入。
其中,NoteDao重写了父类AbstractDao的bindValues方法,进行相对应对象数据的绑定,
updateKeyAfterInsertAndAttach(entity, rowId, true)是为了更新自增主键的id,将实体放入缓存中。
删除对象delete:
noteDao.deleteByKey(id);
底层源码的实现是:
public void deleteByKey(K key) { assertSinglePk(); SQLiteStatement stmt = statements.getDeleteStatement(); if (db.isDbLockedByCurrentThread()) { synchronized (stmt) { deleteByKeyInsideSynchronized(key, stmt); } } else { // Do TX to acquire a connection before locking the stmt to avoid deadlocks db.beginTransaction(); try { synchronized (stmt) { deleteByKeyInsideSynchronized(key, stmt); } db.setTransactionSuccessful(); } finally { db.endTransaction(); } } if (identityScope != null) { identityScope.remove(key); } }
删除对象与插入对象相似,删除操作目前仅支持操作单一主键的表,
assertSinglePk()是判断对象是否是单一主键,若不是则抛出错误,
if (identityScope != null) { identityScope.remove(key); }
判断是否使用缓存机制,是的话删除缓存中的实体。
修改对象update:
noteDao.insertOrReplace(note);
底层源码的实现是:
private long executeInsert(T entity, SQLiteStatement stmt) { long rowId; if (db.isDbLockedByCurrentThread()) { synchronized (stmt) { bindValues(stmt, entity); rowId = stmt.executeInsert(); } } else { // Do TX to acquire a connection before locking the stmt to avoid deadlocks db.beginTransaction(); try { synchronized (stmt) { bindValues(stmt, entity); rowId = stmt.executeInsert(); } db.setTransactionSuccessful(); } finally { db.endTransaction(); } } updateKeyAfterInsertAndAttach(entity, rowId, true); return rowId; }
同样,
updateKeyAfterInsertAndAttach(entity, rowId, true)同插入操作。
查找对象Search:
greendao提供提供多种查找方式进行查找。
List<Note> list = getNoteDao().queryBuilder().where(NoteDao.Properties.Text.eq("test")).build().list();
Note note = noteDao.load((long) 1);
查找对象的实现实现是原理是传入多个限制条件,然后在底层代码中拼接sql查询语句进行查询,然后在转换成相对应的对象。查询的机制跟其他操作方式一样,如果有使用greendao的缓存机制,则先从缓存中获取,再从数据库获取,如果没有使用缓存机制,则直接从数据库中获取。
如果需要使用更复杂的查询方法的话,可以查看Property类和QueryBuilder的源码,greendao提供多种方式的拼接,可以组成日常开发中经常用到的查询语句。
需要一提的是greendao的懒加载功能:
参考资料:
http://greenrobot.org/
http://blog.csdn.net/xushuaic/article/details/24434881
http://blog.csdn.net/xushuaic/article/details/24438841
http://blog.csdn.net/xushuaic/article/details/24496191
相关文章推荐
- Androidx学习笔记(20)-- SQLite创建 增删改查(普通方式和API方式)
- Android系统进程间通信(IPC)机制Binder中的Server启动过程源代码分析
- [iOS]提交App报错ERROR ITMS -90207
- 30岁以上的成年人要有自己独立理性的推断力
- shell编程快速入门
- ddd
- [8]姥爷幽默谈Objective-C-继承,多态,封装
- 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得Service Manager接口之路
- Androidx学习笔记(19)-- SQLite 简介
- Add Binary
- PHP学习笔记 Win平台下PHP开发环境的搭建
- 使用css垂直水平居中
- JSONArray 的 fromObject()方法执行时报错问题
- sbt入门与进阶
- Codeforces Round #252 (Div. 2) B. Valera and Fruits(模拟)
- 51.com 对于6个月未登录的用户,相册进行清空处理
- AJAX入门学习笔记
- 一起talk C栗子吧(第一百一十回:C语言实例--线程标识符)
- 浅谈Service Manager成为Android进程间通信(IPC)机制Binder守护进程之路
- NSMutableDictionary 崩溃原因之immutable