市面上的一些数据库框架:ORMLite、Afinal、ActiveAndroid、SugarORM、GreenDao、Realm
ORMLite
简单的介绍如下:
- OrmLite
OrmLite 不是 Android 平台专用的ORM框架,它是Java ORM。支持JDBC连接,Spring以及Android平台。语法中广泛使用了注解(Annotation)。
- SugarORM
SugarORM 是 Android 平台专用ORM。提供简单易学的APIs。可以很容易的处理1对1和1对多的关系型数据,并通过3个函数save(), delete() 和 find() (或者 findById()) 来简化CRUD基本操作。
- GreenDAO
当性能很重要时(数据访问频繁),GreenDao是一个很快的解决方案,它能够支持数千条记录的CRUD每秒,和OrmLite相比,GreenDAO要快几乎4.5倍。(准确数据请自行benchmark)。
GreenDAO小于100KB,所以对于应用程序APK的大小影响很小。
- Active Android
Active Record(活动目录)是Yii、Rails等框架中对ORM实现的典型命名方式。Active Android 帮助你以面向对象的方式来操作SQLite。
在你的项目中包含Active Android,你需要在项目的 /libs 目录下添加一个jar文件。可以从Github中获取源代码并使用Maven进行编辑。
- Realm
Realm 是一个将可以使用的Android ORM,基于C++编写,直接运行在你的设备硬件上(不需要被解释),因此运行很快。它同时是开源跨平台的,iOS的代码可以在GitHub找到,你还可以找到Objective C以及Swift编写的Realm使用实例。
ArrayList<HashMap<String ,String>> list = new ArrayList<HashMap<String, String>>();
39
40 /**Cursor是结果集游标,使用Cursou.moveToNext()方法可以从当前行移动到下一行**/
41 Cursor cursor = sqLiteDatabase.rawQuery(sql , bindArgs);
42 int clos_len = cursor.getColumnCount(); //获取数据所有列数
43
44 Log.i("TAG:","querySQLite()方法中获得总列数clos_len:" + clos_len);
45
46 boolean isfals = cursor.moveToNext();
47 Log.i("TAG:","isfals值为:" + isfals);
48
49 while(cursor.moveToNext()) { //循环表格中的每一行
50 Log.i("TAG:","进入到while循环中");
51
52 HashMap<String , String> map = new HashMap<>();
53 for(int i = 0;i<clos_len;i++){ //循环表格中的每一列
54 String clos_name = cursor.getColumnName(i); //从给定的索引i返回列名
55 String clos_value = cursor.getString(cursor.getColumnIndex(clos_name));//返回指定的名称,没有就返回-1
56 if(clos_value==null){
57 clos_value = "";
58 }
59
60 Log.i("TAG:","while循环下面的for循环拿到的数据clos_value为:"
61 + cursor.getString(cursor.getColumnIndex(clos_name)));
62
63 map.put(clos_name , clos_value);
64 }
65 list.add(map);
66 }
67 return list;
特征:底层数据库都是基于开源的SQLite实现,然后在系统层封装成用于应用层的API,虽然直接使用系统的数据库API性能很高,但是这些API接口并不是很方便开发者使用,一不小心就会引入Bugs,而且代码的视觉效果也不好,为了解决这个问题,一系列的对象关系映射(ORM)框架出现
标题Greendao使用
定义:Greendao的本质是为存储在关系数据库Sqlite中的数据提供面向对象的界面,使用过程中,我们只需定义数据模型,而GreenDAO将创建Java数据对象(实体)和DAO(数据访问对象)。
特征:
1.对象/关系映射(ORM Object Relation mapping)
下面是一张对象关系映射图
2.微小的依赖库
GreenDao关键依赖库大小不超过100kb,So,也不会出现因为引入GreenDao而出现65k问题
3.自动生成代码
使用GreenDao,我们无需关注实体类以及Dao,GreenDao已为我们自动生成了
4.开源
GreenDao 更新日志
从2017年开始greendao这个项目已经没有更新了
使用:
1.配置Gradle
classpath 'org.greenrobot:greendao-gradle-plugin:3.1.1'//add for greendao
2.添加应用插件
apply plugin: 'org.greenrobot.greendao'//add for greendao
3.添加库文件
implementation "org.greenrobot:greendao:3.1.1"
4.初始化Greendao的配置
greendao {
schemaVersion 66 (当前数据库版本)
daoPackage '包名.db.generator'(生成的Dao,DaoMaster和DaoSession的包名称)
targetGenDir 'src/main/java'(存储的位置,默认为构建目录( build / generated / source / greendao))
}
注意点:当你的数据库在版本升级的时候会自动把表单进行删除,所以当你需要自己管理自己的数据库版本的时候,你需要自己实现DaoMaster.OpenHelper,来进行版本升级管理,有一个开源解决办法MigrationHelper类,可以用这个
5.编写所需要的实体类,然后build下就ok
@Entity(nameInDb = "article_list")
public class ArticleItemBean implements Parcelable, Cloneable {
@Id(autoincrement = true)
private Long id;
//去掉唯一键,
@Unique
public String newsId = "";
public double score;
public int template;
public int commentNum;
//下面我省略了一些代码,这是greendao自己生成的就不用管了
}
6.通过DaoSession来操作你写的数据库,举个例子根据newsid来进行查找
// 创建数据
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(context, "article-db", null);
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDatabase());
DaoSession daoSession = daoMaster.newSession();
ArticleItemBeanDao dao = daoSession.getArticleItemBeanDao();
//查找
dao.queryBuilder().where(ArticleItemBeanDao.Properties.NewsId.eq(newsId)).unique();
DaoMaster:保存数据库的对象并管理特定模式的Dao类,它具有静态方法来创建表或者将他们删除,一个DaoMaster就代表着一个数据库的连接
DaoSession:管理特定模式的所有可用的Dao类,有一些方法,插入加载更新删除等操作,DaoSession可以创建多个,每一个都是属于同一个数据库的连接
Dao层:数据访问对象持续存在并查询实体
7.注解,红色标记一般是常用的
源码分析:
1.创建数据库
DaoMaster.OpenHelper openHelper = new DaoMaster.OpenHelper(){...}
daoMaster = new DaoMaster(openHelper.getWritableDb());
主要看openHelper.getWritableDb()
进入到这个方法如下
public abstract class DatabaseOpenHelper extends SQLiteOpenHelper {
/**
* Like {@link #getWritableDatabase()}, but returns a greenDAO abstraction of the database.
* The backing DB is an standard {@link SQLiteDatabase}.
*/
public Database getWritableDb() {
return wrap(getWritableDatabase());
}
}
在往下看getWritableDatabase()
public abstract class SQLiteOpenHelper{
public SQLiteDatabase getWritableDatabase() {
synchronized (this) {
return getDatabaseLocked(true);
}
}
private SQLiteDatabase getDatabaseLocked(boolean writable) {
///这是一系列异常判断可以直接忽略
if (version > 0 && version < mMinimumSupportedVersion) {
File databaseFile = new File(db.getPath());
onBeforeDelete(db);
db.close();
if (SQLiteDatabase.deleteDatabase(databaseFile)) {
mIsInitializing = false;
return getDatabaseLocked(writable);
} else {
throw new IllegalStateException("Unable to delete obsolete database "
+ mName + " with version " + version);
}
} else {
db.beginTransaction();
try {
if (version == 0) {
//这里就是关键的地方创建表单了
onCreate(db);
} else {
if (version > mNewVersion) {
onDowngrade(db, version, mNewVersion);
} else {
//进行升级操作,自己在本地实现
onUpgrade(db, version, mNewVersion);
}
}
db.setVersion(mNewVersion);
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
}
onOpen(db);
if (db.isReadOnly()) {
Log.w(TAG, "Opened " + mName + " in read-only mode");
}
mDatabase = db;
return db;
} finally {
mIsInitializing = false;
if (db != null && db != mDatabase) {
db.close();
}
}
}
}
在往下看
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 66;
/** Creates underlying database table using DAOs. */
public static void createAllTables(Database db, boolean ifNotExists) {
//创建了一个个的表
AppListBeanDao.createTable(db, ifNotExists);
}
到此为止是把数据库中的表全部创建完全
然后将数据库的表与实体类进行关联
还是回到
daoMaster = new DaoMaster(openHelper.getWritableDb());
进入到DaoMaster的构造方法中
public DaoMaster(Database db) {
super(db, SCHEMA_VERSION);
registerDaoClass(AppListBeanDao.class);
}
进入到registerDaoClass方法里
public abstract class AbstractDaoMaster {
protected final Database db;
protected final int schemaVersion;
protected final Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> daoConfigMap;
public AbstractDaoMaster(Database db, int schemaVersion) {
this.db = db;
this.schemaVersion = schemaVersion;
daoConfigMap = new HashMap<Class<? extends AbstractDao<?, ?>>, DaoConfig>();
}
protected void registerDaoClass(Class<? extends AbstractDao<?, ?>> daoClass) {
//这个DaoConfig就是将数据库和实体类进行了关联
DaoConfig daoConfig = new DaoConfig(db, daoClass);
daoConfigMap.put(daoClass, daoConfig);
}
2.DaoSeesion
DaoSession对象是通过master.newSession();创建的。DaoSession对象是连接GreenDao框架到SQLite数据库的纽带,通过该对象我们可以得到一个与数据库某个表相关的操作对象xxxDao
daoSession = getDaoMaster().newSession();
进入到newSession()这个方法里去
public class DaoMaster extends AbstractDaoMaster{
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
}
在往下看
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
appListBeanDaoConfig = daoConfigMap.get(AppListBeanDao.class).clone();
appListBeanDaoConfig.initIdentityScope(type);
}
这个daoConfigMap保存了数据库db与实体类之间的联系,当我们用XXXDao类进行增删查改的时候对应的数据库也会进行对应的操作