GreenDAO系列之(1)入門
關於greenDao
簡介
greenDAO 是一個開源的ORM資料庫框架。它幫助開發者從日常的資料庫的讀寫sql語句中解放出來,開發者只需要關注具體的Java物件,就能夠進行資料庫的訪問操作。
greenDao features
1.強大的效能,可能是ORM資料庫中效能最好的。官方把greenDao和OrmLite、ActiveAndroid做的效能對比,資料如下:
- 易於使用的API
- 低記憶體消耗
- 包size比較小,如果不包含加密,大概proguard後的包size為8k。
- 支援資料庫加密: 支援SQLCipher。SQLCipher對個人開發者來說倒不錯,不過對於公司來說吸引力不大。
greenDao 核心類說明
如上圖所示,greenDao有幾個核心類:
- DaoMaster : db的管理類,是db的總入口,總管的角色,管理著database建立、更新以及資料庫中有哪些表之類。每一個db對應一個DaoMaster。
- DaoSession : 會話, 管理指定的schema的所有dao,另外DaoSession也支援資料快取,可以指定dao是否使用快取。
- xxxDao : 某個table的操作物件
- Entity : 通俗易懂,不解釋了
greenDao工程說明
greenDao 的github包含兩個公共元件 :
- DaoCore :greenDao的核心框架,我們一般說的greenDao就是指這個
- DaoGenerator :通俗易懂,就是xxxDao的生成器,幫助開發者生成xxxDAO物件,開發者只需要定義自己的Entity,通過DaoGenrator就能夠生成對應的xxxDao物件。
新手接入
這裡演示一個學生的例子
1.建立自己的Android Project,前戲就不貼了
2.匯入greenDao
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath `org.greenrobot:greendao-gradle-plugin:3.2.1`
}
}
apply plugin: `org.greenrobot.greendao`
dependencies {
compile `org.greenrobot:greendao:3.2.0`
}
3.編寫Entity
我們定義一個Student class:
@Entity
public class Student {
@Id
private String mId;
private String mName;
private int mGender;
}
@Entity和@Id是greenDao的標籤,分別用來表示這是個Entity以及Entity的主鍵,greenDao Generator會根據這些標籤自動生成DaoMaster、DaoSession、StudentDao。 具體的標籤的使用方法可以檢視官方文件。
4、點選Run, 最後生成的程式碼如下(部分加了註釋):
DaoMaster.java
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* Master of DAO (schema version 1): knows all DAOs.
*/
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
public static void createAllTables(Database db, boolean ifNotExists) {
StudentDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(Database db, boolean ifExists) {
StudentDao.dropTable(db, ifExists);
}
/**
* WARNING: Drops all table on Upgrade! Use only during development.
* Convenience method using a {@link DevOpenHelper}.
*/
public static DaoSession newDevSession(Context context, String name) {
Database db = new DevOpenHelper(context, name).getWritableDb();
DaoMaster daoMaster = new DaoMaster(db);
return daoMaster.newSession();
}
public DaoMaster(SQLiteDatabase db) {
this(new StandardDatabase(db));
}
public DaoMaster(Database db) {
super(db, SCHEMA_VERSION);
registerDaoClass(StudentDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
/**
* Calls {@link #createAllTables(Database, boolean)} in {@link #onCreate(Database)} -
*/
public static abstract class OpenHelper extends DatabaseOpenHelper {
public OpenHelper(Context context, String name) {
super(context, name, SCHEMA_VERSION);
}
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(Database db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
//建立資料庫
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name) {
super(context, name);
}
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
//資料庫升級。。。非常霸道,直接清除表後重建,我們實際專案中肯定不會這麼使用的
dropAllTables(db, true);
onCreate(db);
}
}
}
DaoSession.java :
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
*
* @see org.greenrobot.greendao.AbstractDaoSession
*/
public class DaoSession extends AbstractDaoSession {
private final DaoConfig studentDaoConfig;
private final StudentDao studentDao;
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
studentDaoConfig = daoConfigMap.get(StudentDao.class).clone();
//設定快取型別
studentDaoConfig.initIdentityScope(type);
studentDao = new StudentDao(studentDaoConfig, this);
registerDao(Student.class, studentDao);
}
//清除快取
public void clear() {
studentDaoConfig.clearIdentityScope();
}
public StudentDao getStudentDao() {
return studentDao;
}
}
StudentDao.java
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* DAO for table "STUDENT".
*/
public class StudentDao extends AbstractDao<Student, String> {
public static final String TABLENAME = "STUDENT";
/**
* 定義Studnet表的Column
*/
public static class Properties {
public final static Property MId = new Property(0, String.class, "mId", true, "M_ID");
public final static Property MName = new Property(1, String.class, "mName", false, "M_NAME");
public final static Property MGender = new Property(2, int.class, "mGender", false, "M_GENDER");
}
public StudentDao(DaoConfig config) {
super(config);
}
public StudentDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** 建立Student表,這種建立方法有點太low了居然i無法做到自動建立 */
public static void createTable(Database db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + ""STUDENT" (" + //
""M_ID" TEXT PRIMARY KEY NOT NULL ," + // 0: mId
""M_NAME" TEXT," + // 1: mName
""M_GENDER" INTEGER NOT NULL );"); // 2: mGender
}
/** Drops the underlying database table. */
public static void dropTable(Database db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + ""STUDENT"";
db.execSQL(sql);
}
/**
* 插入語句時繫結的資料,這種寫法有點坑,萬一MId為空時,生成的語句就有w
*/
@Override
protected final void bindValues(DatabaseStatement stmt, Student entity) {
stmt.clearBindings();
String mId = entity.getMId();
if (mId != null) {
stmt.bindString(1, mId);
}
String mName = entity.getMName();
if (mName != null) {
stmt.bindString(2, mName);
}
stmt.bindLong(3, entity.getMGender());
}
@Override
protected final void bindValues(SQLiteStatement stmt, Student entity) {
stmt.clearBindings();
String mId = entity.getMId();
if (mId != null) {
stmt.bindString(1, mId);
}
String mName = entity.getMName();
if (mName != null) {
stmt.bindString(2, mName);
}
stmt.bindLong(3, entity.getMGender());
}
@Override
public String readKey(Cursor cursor, int offset) {
return cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0);
}
/**
* 從sql讀取資料,生成student物件
*/
@Override
public Student readEntity(Cursor cursor, int offset) {
Student entity = new Student( //
cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0), // mId
cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // mName
cursor.getInt(offset + 2) // mGender
);
return entity;
}
@Override
public void readEntity(Cursor cursor, Student entity, int offset) {
entity.setMId(cursor.isNull(offset + 0) ? null : cursor.getString(offset + 0));
entity.setMName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
entity.setMGender(cursor.getInt(offset + 2));
}
@Override
protected final String updateKeyAfterInsert(Student entity, long rowId) {
return entity.getMId();
}
@Override
public String getKey(Student entity) {
if(entity != null) {
return entity.getMId();
} else {
return null;
}
}
@Override
public boolean hasKey(Student entity) {
return entity.getMId() != null;
}
@Override
protected final boolean isEntityUpdateable() {
return true;
}
}
5.使用
- 初始化資料庫
DevOpenHelper helper = new DevOpenHelper(this, "students");
Database db = helper.getWritableDb();
mDaoSession = new DaoMaster(db).newSession();
mStudentDao = mDaoSession.getStudentDao();
- 新增
Student student = new Student();
student.setMId(String.valueOf(System.currentTimeMillis()));
student.setMName("name"+System.currentTimeMillis());
student.setMGender((int) (System.currentTimeMillis()%2));
mStudentDao.insert(student);
- 刪除
final Student deleteStudent = mStudentDao.queryBuilder().orderDesc(StudentDao.Properties.MId).limit(1).unique();
mStudentDao.delete(deleteStudent);
小結
從上面的demo,可以看到訪問資料庫的過程變得非常的簡單。開發者只需要定義自己的entity,greenDao Generator就能自動生成對應的類檔案。整個使用過程非常簡單,但是,一般說到但是,就是來講它的壞話了。。。我們也看到greenDao有如下幾個問題:
- greenDao Generator仍然有點笨,生成的程式碼真心是笨(如:要是我們的變數是以m開頭,則會生成 getM,setM方法。),還需要我們進一步加工,才能變成比較美觀的程式碼。
- greenDao的DaoMaster在資料庫的建立以及更新上都使用了指定sql語句的方法,比較笨拙,雖然網上有一個叫做MigrationHelper的解決方案,但仍不夠友好。後續再給大家介紹一下我們使用的方法。
- xxxDao的Property支援的屬性有限
如:Property.java
public final int ordinal;
public final java.lang.Class<?> type;
public final java.lang.String name;
public final boolean primaryKey;
public final java.lang.String columnName;
不支援default、is null、unique 等屬性
Reference: https://github.com/greenrobot/greenDAO
相關文章
- Python系列之-1、Django入門PythonDjango
- Rust入門系列之語言特性 - 1Rust
- redis系列1-入門Redis
- 入門系列之Kubernetes部署
- Java入門系列之finalJava
- 《xhtml入門系列》之四HTML
- Rust入門系列之切片Rust
- Knative 入門系列1:knative 概述
- SpringBoot系列(1)——AOP-入門Spring Boot
- Java入門系列之重寫Java
- SpringCloud 2020.0.4 系列之 Gateway入門SpringGCCloudGateway
- nacos入門系列之配置中心
- Python 入門系列 —— 1. 簡介Python
- React從入門到精通學習系列之(1)安裝ReactReact
- Rust入門系列之引用和借用Rust
- Laravel 5.4 入門系列 1. 安裝Laravel
- Docker 入門及安裝[Docker 系列-1]Docker
- Spring Security系列之入門應用(二)Spring
- Spring全家桶系列–SpringBoot之入門JPASpring Boot
- Java教程:nacos入門系列之配置中心Java
- 瞎說系列之Object.assign入門Object
- Flutter 入門指北(Part 1)之 DartFlutterDart
- 從0到1使用Kubernetes系列——Kubernetes入門
- 瞎說系列之正規表示式入門
- WebSocket系列之基礎知識入門篇Web
- Helm使用者指南-系列(1)-序言+快速入門
- Java入門到實踐系列(1)——Java簡介Java
- HTML之小白的入門Day1HTML
- shell入門系列
- greenDAO資料庫之修改儲存地址資料庫
- shiro實戰系列(二)之入門實戰續
- Go語言入門系列(四)之map的使用Go
- WPF入門教程系列二十四——DataGrid使用示例(1)
- ML.NET技術研究系列1-入門篇
- Three.js入門篇之1 - WebGL on HTMLJSWebHTML
- ORM框架之GreenDao3.0使用詳解(二)ORM框架
- Spring Security系列之極速入門與實踐教程Spring
- SpringBoot系列之Elasticsearch極速入門與實際教程Spring BootElasticsearch
- Go語言入門系列(六)之再探函式Go函式