Sqlite作為android重要的數據存儲庫,原生類SQLiteOpenHelper使用起來繁瑣容易出錯,本著"偷懶"的目的,來學習一下當下十分受歡迎的ORM 框架: greenDAO;網上教程不少,但是大都是針對3.0之前的版本,greenDAO2和3的構建和生成代碼的方式區別很大,最終還是通過greenDAO github上的介紹,慢慢摸索,成功的在項目中構建了greenDAO,本文章寫于greenDao更新至3.2版本
一、什么是greenDAO?
官方介紹:
greenDAO github
greenDAO 官網
網友的博客:
Android ORM框架 GreenDao3.0的使用
greenDAO3開始使用注解的方式定義實體類(entity),并且是通過安裝gradle插件來生成代碼。
二、如何使用greenDAO
構建之前,不熟悉gradle概念的同學建議學習Gradle for android 系列教程
先來看下greenDAO 官方構建介紹:
開始搭建:
- github中提示添加maven倉庫,但是android studio 項目已經默認包含了jcenter倉庫,而jcenter倉庫就是maven倉庫的一個分支,因此我們不要再添加倉庫,直接添加classPath即可
- 在moudle下的build.gradle文件中 申明插件以及配置greendao(可以不配置)
- 并在dependencies中添加compile
/* green dao */
compile 'org.greenrobot:greendao:3.2.0
三、使用greenDAO
- 編寫實體類:User類,使用greendao @Entity注解
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
@Entity
public class User {
@Id
private long id;
private String userName;
private int age;
private String gender;
}
- 編譯項目,build后greendao插件會為所有帶有該注解的實體生成Dao文件,以及DaoManager與DaoSession,默認生成目錄為build/generated/source ,如果我們在gradle腳本中配置了,則會生成在我們的配置目錄
不配置,則在默認目錄(build/generated/source/greendao)下生成dao文件:
四、greenDAO 注解
1.實體@Entity注解
schema:告知GreenDao當前實體屬于哪個schema
active:標記一個實體處于活動狀態,活動實體有更新、刪除和刷新方法
nameInDb:在數據中使用的別名,默認使用的是實體的類名
indexes:定義索引,可以跨越多個列
createInDb:標記創建數據庫表
2.基礎屬性注解
@Id :主鍵 Long型,可以通過@Id(autoincrement = true)設置自增長
@Property:設置一個非默認關系映射所對應的列名,默認是的使用字段名 舉例:@Property (nameInDb="name")
@NotNul:設置數據庫表當前列不能為空
@Transient :添加次標記之后不會生成數據庫表的列
3.索引注解
@Index:使用@Index作為一個屬性來創建一個索引,通過name設置索引別名,也可以通過unique給索引添加約束
@Unique:向數據庫列添加了一個唯一的約束
4.關系注解
@ToOne:定義與另一個實體(一個實體對象)的關系
@ToMany:定義與多個實體對象的關系
五、使用greenDAO 進行數據操作(詳情可查閱博友的文章)
- 使用單例模式構建一個工具類來獲取daoSession等對象
public class GreenDaoHelper {
private static DaoMaster.DevOpenHelper devOpenHelper;
private static SQLiteDatabase database;
private static DaoMaster daoMaster;
private static DaoSession daoSession;
/**
* 初始化greenDao
* 建議放在Application 中進行
*/
public static void initDatabase(){
// 通過 DaoMaster 的內部類 DevOpenHelper,你可以得到一個便利的 SQLiteOpenHelper 對象。
// 可能你已經注意到了,你并不需要去編寫「CREATE TABLE」這樣的 SQL 語句,因為 greenDAO 已經幫你做了。
// 注意:默認的 DaoMaster.DevOpenHelper 會在數據庫升級時,刪除所有的表,意味著這將導致數據的丟失。
// 所以,在正式的項目中,你還應該做一層封裝,來實現數據庫的安全升級。
devOpenHelper = new DaoMaster.DevOpenHelper(AppContext.getInstance(),"cache-db",null);//數據庫名
database = devOpenHelper.getWritableDatabase();
// 注意:該數據庫連接屬于 DaoMaster,所以多個 Session 指的是相同的數據庫連接。
daoMaster = new DaoMaster(database);
daoSession = daoMaster.newSession();
}
public static DaoSession getDaoSession() {
return daoSession;
}
public static SQLiteDatabase getDb() {
return database;
}
}
數據庫的增刪改查我們都將通過Dao來操作
- 增加數據(直接inser一個對象即可,十分簡便)
private UserDao mUserDao = GreenDaoHelper.getDaoSession().getUserDao();
public void insertData(){
//數據庫的增刪改查我們都將通過UserDao來進行,插入操作如下:
mUserDao.insert(new User(null,"david",23,"male"));//id傳null 即自增。==> 這里是Long類型而不是long
}
小手一抖,一口氣插了6條數據:
- 刪除數據(刪除數據和修改數據的思路一樣,都是要先查找到數據),操作很簡單,效果就不一一截圖了
//查詢id等于3的所有行并刪除
User user = mUserDao.queryBuilder().where(UserDao.Properties.Id.eq(3)).build().unique();
if (user == null) ToastUtils.show(getView(), "用戶不存在!");
else mUserDao.deleteByKey(user.getId());
//查詢id小于5的集合并刪除
List<User> userList = (List<User>) mUserDao.queryBuilder().where(UserDao.Properties.Id.le(5)).build().list();
for (User user : userList) {
mUserDao.delete(user);
}
//刪除所有數據
mUserDao.deleteAll();
- 修改數據
//修改id為2的行
User user = new User((long) 2, "Nancy", 23, "female");
mUserDao.update(user);
//查詢id>= 3 且like ("%david%")
User user = mUserDao.queryBuilder()
.where(UserDao.Properties.Id.ge(3), UserDao.Properties.UserName.like("%david%")).build().unique();
if (user == null) {
ToastUtils.show(getView(), "用戶不存在!");
} else {
user.setUserName("王五");
mUserDao.update(user);
}
- 查詢數據
//查出所有數據
List<User> users = mUserDao.loadAll();
//查詢id為1~4之間的數,查出前2個
List<User> users = mUserDao.queryBuilder()
.where(UserDao.Properties.Id.between(1, 4)).limit(2).build().list();
六、數據庫升級
數據庫升級的意義:
如果我們再項目中使用了數據庫。而數據庫的結構在第一版的時候定下來,之后發布功能更新,或增加業務邏輯,原來的數據庫結構可能就不適用了。而如果數據庫的結構與之前版本的結構不同,新版本的應用讀取舊數據庫肯定會出問題。解決辦法只有兩種:
1.讓用戶卸載老版本再安裝新的程序;
2.軟件自行更新數據庫結構。
第一種辦法很明顯不具備可操作性,而且用戶一旦卸載軟件,數據就丟失了,這是不能容忍的事情。因此,作為開發者必須妥善處理數據庫的升級問題。
- 修改gradle文件
首先在module的gradle文件中修改版本號:
//改為最新的版本號
schemaVersion 2
如果只是做了上面的步驟則會默認清除所有數據,一看源碼便知,當檢測到version變化的時候便執行dropAllTables()操作,再重新建庫
/** 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);
}
}
數據遷移的核心思想:
1 把舊表改為臨時表
2 建立新表
3 臨時表數據寫入新表,刪除臨時表
站在巨人的肩膀上,這里直接使用了開源的庫,配合greenDAO來做數據遷移,親測穩定:
GreenDaoUpgradeHelper
schemaVersion 版本加1,User類新增屬性:major
不做遷移處理前,重新安裝后數據庫已經被重置,數據為空。遷移配置后,舊表數據已經被存到新表中,major字段為null;
使用方式該git上面介紹的很詳細了,不再贅述。
感謝前輩們的無私分享。