介紹
GreenDao是一個開源的 Android ORM嵌入式關(guān)系數(shù)據(jù)庫,通過將 Java 對象映射到數(shù)據(jù)庫表(稱為 ORM,“對象/關(guān)系映射”) ,使用一個簡單的面向?qū)ο蟮?API 來存儲、更新、刪除和查詢 Java 對象。
GreenDao特點
- 最佳性能 (可能是 Android 中最快的 ORM) ,基準測試也是開源的;
- 易于使用的功能強大的 api,涵蓋關(guān)系和連接;
- 最小的內(nèi)存消耗;
- 小型庫大小(< 100KB) ,以保持較低的構(gòu)建時間,并避免65k 方法限制;
- 數(shù)據(jù)庫加密:greenDAO 支持 SQLCipher 來保證用戶數(shù)據(jù)的安全;
- 強大而活躍的社區(qū)交流支持。
Github地址 https://github.com/greenrobot/greenDAO
項目配置
-
項目目錄下
.gradle文件配置:buildscript { repositories { google() jcenter() // GreenDao倉庫 mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:3.5.4' // GreenDao插件 classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' } } -
app目錄下
.gradle配置apply plugin: 'com.android.application' //GreenDao插件 apply plugin: 'org.greenrobot.greendao'dependencies { //GreenDao依賴添加 implementation 'org.greenrobot:greendao:3.2.2' }greendao { // 數(shù)據(jù)庫版本號 schemaVersion 1 // 生成數(shù)據(jù)庫文件的目錄 targetGenDir 'src/main/java' // 生成的數(shù)據(jù)庫相關(guān)文件的包名 daoPackage 'com.nianlun.greendao.gen' }
使用說明
1、 首先新建用戶實體類,如下:
@Entity
public class User {
@Id(autoincrement = true)
private Long id;
@Unique
private String userId;
@Property
private String userName;
@Property
private int age;
}
實體類中詳細注解說明:
-
@Entity:表明這個實體類會在數(shù)據(jù)庫中生成一個與之相對應(yīng)的表,其中可配置項:
nameInDb:可以自定義表名,表明該實體對應(yīng)數(shù)據(jù)庫中的那張表,默認為實體類名;
indexes:定義索引,這里可跨越多個列;
createInDb:如果是有多個實體都關(guān)聯(lián)這個表,可以把多余的實體里面設(shè)置為false避免重復創(chuàng)建(默認是true);
schema:一個項目中有多個schema時,表明要讓這個dao屬于哪個schema;
active:是否應(yīng)該生成更新/刪除/刷新方法。如果Entity定義了 @ToOne 或 @ToMany關(guān)系,那么獨立于該值是有效的。意為是否支持實體類之間update,refresh,delete等操作。
@Id:對應(yīng)數(shù)據(jù)表中的主鍵,是一條數(shù)據(jù)的唯一標識。如果實體沒有聲明主鍵,默認創(chuàng)建Long類型主鍵"_id"自增。使用Long類型主鍵時可以通過@Id(autoincrement = true)設(shè)置為自增。
@Property(nameInDb = "USER_NAME" ):可以自定義字段名,注意外鍵不能使用該屬性。表明這個屬性對應(yīng)數(shù)據(jù)表中的 USER_NAME 字段。
@NotNull:該屬性值不能為空。
@Transient:該屬性不會被存入數(shù)據(jù)庫中。
@Unique:表明該屬性在數(shù)據(jù)庫中只能有唯一值。
@Index:創(chuàng)建一個索引。通過name設(shè)置索引別名,也可以通過unique給索引添加約束。
@Convert:指定一個PropertyConverter用于支持自定義類型(沒用過)。
@ToOne:定義自己與一個實體對象的關(guān)系。
@ToMany:定義自己與多個實體對象的關(guān)系(可不與@ToOne聯(lián)合使用)。@ToMany的屬性referencedJoinProperty,類似于外鍵約束。
@JoinProperty:對于更復雜的關(guān)系,可以使用這個注解標明目標屬性的源屬性,起關(guān)聯(lián)作用。
@JoinEntity:如果你在做多對多的關(guān)系,有其他的表或?qū)嶓w參與,可以給目標屬性添加這個額外的注解。
@OrderBy:指定{@ToMany}關(guān)系的相關(guān)集合的排序,(propertyA, propertyB)默認為按主鍵ASC排序。
@Generated:這個是build后greendao自動生成的,這個注解理解為防止重復,每一塊代碼生成后會加個hash作為標記。
2、 實體類建完畢后,通過點擊AndroidStudio中的Make Project(小錘子的圖標),便發(fā)現(xiàn)GreenDao為我們的User實體類生成了對應(yīng)的Getter、Setter方法以及倆個構(gòu)造函數(shù),同時在我們配置的com.nianlun.greendao.gen包下生成了三個對應(yīng)類文件DaoMaster、DaoSession和UserDao,之后所有相關(guān)的數(shù)據(jù)庫操作都依靠這三個文件了:
- DaoMaster:使用greenDAO的切入點。DaoMaster保存數(shù)據(jù)庫對象(SQLiteDatabase)并管理特定模式的DAO類(而不是對象)。 它具有靜態(tài)方法來創(chuàng)建表或?qū)⑺鼈儎h除。 其內(nèi)部類OpenHelper和DevOpenHelper是在SQLite數(shù)據(jù)庫中創(chuàng)建模式的SQLiteOpenHelper實現(xiàn)。一個DaoMaster就代表著一個數(shù)據(jù)庫的連接;
- DaoSession:管理特定模式的所有可用DAO對象,您可以使用其中一個getter方法獲取。 DaoSession還為實體提供了一些通用的持久性方法,如插入,加載,更新,刷新和刪除。 DaoSession可以讓我們使用一些Entity的基本操作和獲取Dao操作類,DaoSession可以創(chuàng)建多個,每一個都是屬于同一個數(shù)據(jù)庫連接的;
- XxDAO:數(shù)據(jù)訪問對象(DAO)持續(xù)存在并查詢實體。 對于每個實體,GreenDAO生成一個DAO。 它比DaoSession有更多的持久化方法,例如:count,loadAll和insertInTx等。
3、數(shù)據(jù)庫操作
(1) 編寫DaoManager,用于創(chuàng)建數(shù)據(jù)庫、創(chuàng)建數(shù)據(jù)庫表、包含增刪改查的操作。
/**
* 創(chuàng)建數(shù)據(jù)庫、創(chuàng)建數(shù)據(jù)庫表、包含增刪改查的操作
*/
public class DaoManager {
private static final String TAG = DaoManager.class.getSimpleName();
private static final String DB_NAME = "RECORD_DB";
private Application mApplication;
//多線程中要被共享的使用volatile關(guān)鍵字修飾
private volatile static DaoManager manager = new DaoManager();
private DaoMaster mDaoMaster;
private DaoMaster.DevOpenHelper mHelper;
private DaoSession mDaoSession;
/**
* 單例模式獲得操作數(shù)據(jù)庫對象
*/
public static DaoManager getInstance() {
return manager;
}
private DaoManager() {
setDebug();
}
public void init(Application application) {
this.mApplication = application;
}
/**
* 判斷是否有存在數(shù)據(jù)庫,如果沒有則創(chuàng)建
*/
public DaoMaster getDaoMaster() {
if (mDaoMaster == null) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(mApplication, DB_NAME, null);
mDaoMaster = new DaoMaster(helper.getWritableDatabase());
}
return mDaoMaster;
}
/**
* 完成對數(shù)據(jù)庫的添加、刪除、修改、查詢操作,僅僅是一個接口
*/
public DaoSession getDaoSession() {
if (mDaoSession == null) {
if (mDaoMaster == null) {
mDaoMaster = getDaoMaster();
}
mDaoSession = mDaoMaster.newSession();
}
return mDaoSession;
}
/**
* 打開輸出日志,默認關(guān)閉
*/
public void setDebug() {
if (BuildConfig.DEBUG) {
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
}
/**
* 關(guān)閉所有的操作,數(shù)據(jù)庫開啟后,使用完畢要關(guān)閉
*/
public void closeConnection() {
closeHelper();
closeDaoSession();
}
public void closeHelper() {
if (mHelper != null) {
mHelper.close();
mHelper = null;
}
}
public void closeDaoSession() {
if (mDaoSession != null) {
mDaoSession.clear();
mDaoSession = null;
}
}
}
(2)編寫CommonDaoUtils,用于完成對數(shù)據(jù)表的操作。
public class CommonDaoUtils<T> {
private DaoSession mDaoSession;
private Class<T> entityClass;
private AbstractDao<T, Long> entityDao;
public CommonDaoUtils(Class<T> pEntityClass, AbstractDao<T, Long> pEntityDao) {
DaoManager mManager = DaoManager.getInstance();
mDaoSession = mManager.getDaoSession();
entityClass = pEntityClass;
entityDao = pEntityDao;
}
/**
* 插入記錄,如果表未創(chuàng)建,先創(chuàng)建表
*/
public boolean insert(T pEntity) {
return entityDao.insert(pEntity) != -1;
}
/**
* 插入多條數(shù)據(jù),在子線程操作
*/
public boolean insertMultiple(final List<T> pEntityList) {
try {
mDaoSession.runInTx(new Runnable() {
@Override
public void run() {
for (T entity : pEntityList) {
mDaoSession.insertOrReplace(entity);
}
}
});
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 修改一條數(shù)據(jù)
*/
public boolean update(T entity) {
try {
mDaoSession.update(entity);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 刪除單條記錄
*/
public boolean delete(T entity) {
try {
//按照id刪除
mDaoSession.delete(entity);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 刪除所有記錄
*/
public boolean deleteAll() {
try {
//按照id刪除
mDaoSession.deleteAll(entityClass);
return true;
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
/**
* 查詢所有記錄
*/
public List<T> queryAll() {
return mDaoSession.loadAll(entityClass);
}
/**
* 根據(jù)主鍵id查詢記錄
*/
public T queryById(long key) {
return mDaoSession.load(entityClass, key);
}
/**
* 使用native sql進行查詢操作
*/
public List<T> queryByNativeSql(String sql, String[] conditions) {
return mDaoSession.queryRaw(entityClass, sql, conditions);
}
/**
* 使用queryBuilder進行查詢
*/
public List<T> queryByQueryBuilder(WhereCondition cond, WhereCondition... condMore) {
QueryBuilder<T> queryBuilder = mDaoSession.queryBuilder(entityClass);
return queryBuilder.where(cond, condMore).list();
}
}
(3)編寫DaoUtilsStore,用于存放及提取DaoUtils。
/**
* 初始化、存放及獲取DaoUtils
*/
public class DaoUtilsStore {
private volatile static DaoUtilsStore instance = new DaoUtilsStore();
private CommonDaoUtils<User> mUserDaoUtils;
public static DaoUtilsStore getInstance() {
return instance;
}
private DaoUtilsStore() {
DaoManager mManager = DaoManager.getInstance();
UserDao _UserDao = mManager.getDaoSession().getUserDao();
mUserDaoUtils = new CommonDaoUtils<>(User.class, _UserDao);
}
public CommonDaoUtils<User> getUserDaoUtils() {
return mUserDaoUtils;
}
}
(4)調(diào)用DaoUtilsStore,進行數(shù)據(jù)操作及查看:
-
初始化生成數(shù)據(jù),進行批量插入:
private void initUser() { //用戶ID生成器 mIdWorker = new SnowflakeIdGenerator(0, 0); DaoUtilsStore.getInstance().getUserDaoUtils().deleteAll(); mUserList = new ArrayList<>(); Random random = new Random(); for (int i = 0; i < 10; i++) { User user = new User(); user.setId((long) i); user.setUserId(String.valueOf(mIdWorker.nextId())); // 隨機生成漢語名稱 user.setUserName(NameUtils.createRandomZHName(random.nextInt(4) + 1)); user.setAge(18 + random.nextInt(10)); mUserList.add(user); } mUserAdapter = new UserAdapter(mUserList); rvUser.setAdapter(mUserAdapter); DaoUtilsStore.getInstance().getUserDaoUtils().insertMultiple(mUserList); } -
查詢數(shù)據(jù)
private void queryAllUser() { mUserList = DaoUtilsStore.getInstance().getUserDaoUtils().queryAll(); mUserAdapter.setNewData(mUserList); rvUser.smoothScrollToPosition(mUserList.size() - 1); } -
插入數(shù)據(jù)
User user = new User(); user.setId((long) mUserList.size()); user.setUserId(String.valueOf(mIdWorker.nextId())); user.setUserName(NameUtils.createRandomZHName(new Random().nextInt(4) + 1)); user.setAge(18 + new Random().nextInt(10)); // 插入新用戶 DaoUtilsStore.getInstance().getUserDaoUtils().insert(user); -
修改數(shù)據(jù)
User user = mUserList.get(mUserList.size() - 1); //刪除最末用戶 DaoUtilsStore.getInstance().getUserDaoUtils().delete(user); -
刪除數(shù)據(jù)
User user = mUserList.get(mUserList.size() - 1); user.setUserName(NameUtils.createRandomZHName(new Random().nextInt(4) + 1)); //更新最末用戶 DaoUtilsStore.getInstance().getUserDaoUtils().update(user);

以上就是GreenDao的簡單介紹接使用說明,更多進階用法如升級、加密等將慢慢補充,并且進一步探索官方推薦的從GreenDao到ObjectBox數(shù)據(jù)庫的集成過程。
訪問Github項目查看具體代碼實現(xiàn):
https://github.com/MickJson/DevelopmentRecord
歡迎點擊查閱及Star,我也會繼續(xù)補充其它有用的知識及例子在項目上。
歡迎點贊/評論,你們的贊同和鼓勵是我寫作的最大動力!