数据库技术博大精深,是当今互联网的基础。前有DB2,后有MySQL、Oracle,然后数据库ORM框架也应运而生。没错,我们这一期讲一讲数据库的ORM技术。
什么是ORM?ORM,全称为Object-Relational Mapping(对象关系映射),由于数据库操作使用到SQL,而SQL是给运维用的,我们程序直接拼接SQL则异常繁琐。所以,就有人提出,这部分繁琐的事情能不能交给框架来做?答案是肯定的。
要理解ORM,首先要掌握Java中比较重要的一个概念,泛型。没有它,就没法很好的开发通用型软件架构。泛型,本质上还是对事物进行了抽象。比如我们现在没法实现的伟大事业,我们可以先想想,它大概是怎样的?比如改造火星。有句话叫做,想象力比知识更重要,这就是抽象的魅力所在。
ORM框架,一定是万能的。给我Book的对象我就能存Book,给我Note的对象我就能存Note。即我使用程序员容易理解的对象模型,来直接操作数据库,那么DAO,数据访问对象,就是桥梁。它是直接跟数据库和SQL打交道的,我们在上层定义一个抽象层来连接真实业务。
在Android端,就有这么一个很好的ORM框架,来帮助我们将数据存储到数据库,它就是GreenDao。我们来看看怎么使用吧!
**项目依赖GreenDao的插件**
在项目根目录的build.gradle依赖插件
```
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
```
并在app模块的build.gradle使用它
```
apply plugin: 'org.greenrobot.greendao'
android {
// 定义APT生成代码的位置和包名
greendao {
schemaVersion 1 daoPackage 'com.xx.greendao'
targetGenDir 'src/main/java'
}
}
```
**app模块依赖GreenDao的包**
```
dependencies {
implementation 'org.greenrobot:greendao:3.2.2'
implementation 'org.greenrobot:greendao-generator:3.2.2'
}
```
**定义实体类**
```
@Entity
public class Note {
@Id(autoincrement = true) private long id;
private String text;
private String comment;
private Date date;
}
```
**在Application中初始化数据库**
```
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "note", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster master = new DaoMaster(db);
DaoSession daoSession = master.newSession();
NoteDao noteDao = daoSession.getNoteDao();
```
通过DaoSession拿到操作具体某张表的DAO。
打住,不好意思,搞错了。我们今天不完全是讲解怎么用GreenDao数据库的,这样使用的文章很多。
增删改查都是通过调用dao的方法就可以了。言归正题,我们自定义的数据缓存框架怎么切换到GreenDao进行缓存?
**定义GreenDaoDatabaseCacheRepository**
```
package dora.cache.repository
import android.content.Context
import dora.cache.holder.*
import me.itangqi.greendao.DaoSession
abstract class GreenDaoDatabaseCacheRepository<T>(context: Context)
: BaseDatabaseCacheRepository<T>(context) {
override fun createCacheHolder(clazz: Class<T>): CacheHolder<T> {
return GreenDaoCacheHolder<T>(getDaoSession(), clazz)
}
override fun createListCacheHolder(clazz: Class<T>): CacheHolder<MutableList<T>> {
return GreenDaoListCacheHolder<T>(getDaoSession(), clazz)
}
abstract fun getDaoSession() : DaoSession
}
```
**定义两个CacheHolder**
```
package dora.cache.holder
import de.greenrobot.dao.AbstractDao
import dora.db.OrmLog
import dora.db.builder.Condition
import me.itangqi.greendao.DaoSession
class GreenDaoCacheHolder<T>(var session: DaoSession, var clazz: Class<T>) : CacheHolder<T> {
private lateinit var dao: AbstractDao<T, Long>
override fun init() {
dao = session.getDao(clazz) as AbstractDao<T, Long>
}
override fun queryCache(condition: Condition): T? {
return session.callInTx {
dao.queryRaw(condition.selection, *condition.selectionArgs)[0]
}
}
override fun removeOldCache(condition: Condition) {
try {
dao.deleteInTx(queryCache(condition))
OrmLog.d("removeOldCache:true")
} catch (e: Exception) {
OrmLog.d("removeOldCache:false")
}
}
override fun addNewCache(model: T) {
try {
dao.insertInTx(model)
OrmLog.d("addNewCache:true")
} catch (e: Exception) {
OrmLog.d("addNewCache:false")
}
}
override fun queryCacheSize(condition: Condition): Long {
return session.callInTx {
dao.count()
}
}
}
```
```
package dora.cache.holder
import de.greenrobot.dao.AbstractDao
import dora.db.OrmLog
import dora.db.builder.Condition
import me.itangqi.greendao.DaoSession
class GreenDaoListCacheHolder<T>(var session: DaoSession, var clazz: Class<T>) : ListCacheHolder<T>() {
private lateinit var dao: AbstractDao<T, Long>
override fun init() {
dao = session.getDao(clazz) as AbstractDao<T, Long>
}
override fun queryCache(condition: Condition): MutableList<T>? {
return session.callInTx {
dao.queryRaw(condition.selection, *condition.selectionArgs)
}
}
override fun removeOldCache(condition: Condition) {
try {
dao.deleteInTx(queryCache(condition))
OrmLog.d("removeOldCache:true")
} catch (e: Exception) {
OrmLog.d("removeOldCache:false")
}
}
override fun addNewCache(models: MutableList<T>) {
try {
dao.insertInTx(models)
OrmLog.d("addNewCache:true")
} catch (e: Exception) {
OrmLog.d("addNewCache:false")
}
}
override fun queryCacheSize(condition: Condition): Long {
return session.callInTx {
dao.count()
}
}
}
```
以上一个是非list模式的,一个是list模式的。切换数据库ORM框架主要就是去重写这两个CacheHolder,用该数据库dao的方法来实现我们的CacheHolder接口。BaseDatabaseCacheRepository更详细的使用,也看我的另两篇文章【Android数据缓存框架 - 切换为Room数据库】https://juejin.cn/post/7158833826771730462 和 【Android数据缓存框架 - 内置ORM功能】https://juejin.cn/post/7139760822309355534 。