greenDAO: Android ORM for your SQLite database
一.什么是GreenDao
Demo鏈接: https://github.com/liumaomao0209/GreenDaoDemo
GreenDAO是一個(gè)開(kāi)源的AndroidORM,使SQLite數(shù)據(jù)庫(kù)的開(kāi)發(fā)再次變得有趣。它在節(jié)省開(kāi)發(fā)時(shí)間的同時(shí)吵血,減輕了開(kāi)發(fā)人員對(duì)低級(jí)別數(shù)據(jù)庫(kù)需求的處理。SQLite是一個(gè)令人敬畏的嵌入式關(guān)系數(shù)據(jù)庫(kù)抛计。盡管如此,編寫(xiě)SQL和解析查詢結(jié)果仍然是非常繁瑣和耗時(shí)的任務(wù)照筑。GreenDAO通過(guò)將Java對(duì)象映射到數(shù)據(jù)庫(kù)表(稱為奧姆吹截,“對(duì)象/關(guān)系映射”)。通過(guò)這種方式凝危,您可以使用簡(jiǎn)單的面向?qū)ο驛PI來(lái)存儲(chǔ)波俄、更新、刪除和查詢Java對(duì)象蛾默。
二.GreenDao的特點(diǎn)
GreenDAO的特點(diǎn)一目了然
- 性能強(qiáng)大 (可能是Android最快的ORM)
- 易用 有強(qiáng)大的API
- 極小內(nèi)存消耗
- 體積小 GreenDAO小于100KB懦铺,所以對(duì)于應(yīng)用程序APK的大小影響很小。
- 數(shù)據(jù)庫(kù)加密 支持SQLCiPHER支鸡,以確保用戶數(shù)據(jù)的安全
當(dāng)性能很重要時(shí)(數(shù)據(jù)訪問(wèn)頻繁)冬念,GreenDao是一個(gè)很快的解決方案,它能夠支持?jǐn)?shù)千條記錄的CRUD每秒牧挣,和OrmLite相比急前,GreenDAO要快幾乎4.5倍。(準(zhǔn)確數(shù)據(jù)請(qǐng)自行benchmark)瀑构。
三.GreenDao的配置
1.導(dǎo)入插件
在project:build.gradle添加如下兩行(位置已注釋)
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
mavenCentral() // 添加
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // 添加
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2.添加依賴和數(shù)據(jù)庫(kù)配置
(1)在app:build.gradle添加library和plugin(位置已經(jīng)注釋為// apply plugin // add library)
(2)數(shù)據(jù)庫(kù)配置信息,在android節(jié)點(diǎn)下
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
android {
compileSdkVersion 28
defaultConfig {
applicationId "com.maomao.technology.greendaodemo"
minSdkVersion 27
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
greendao {
schemaVersion 1 //數(shù)據(jù)庫(kù)版本號(hào)裆针,數(shù)據(jù)庫(kù)升級(jí)使用
daoPackage 'com.maomao.technology.greendaodemo.greendao' //代表GreenDao自動(dòng)生成的有關(guān)數(shù)據(jù)庫(kù)操作工具類所要存放的包名
targetGenDir 'src/main/java' //路徑
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
implementation 'org.greenrobot:greendao:3.2.2' // add library
}
四.GreenDao的使用
首先大概看一下整體構(gòu)建的樣子:
base:數(shù)據(jù)庫(kù)操作的基類
db:對(duì)用戶表專門自定義的操作類.
greendao:建表時(shí)自動(dòng)生成的類.
1.創(chuàng)建一個(gè)用戶類
Generated之下是build后自動(dòng)生成的.
項(xiàng)目的build目錄下或者自己設(shè)定的目錄下還可以看到自動(dòng)生成的三個(gè)類文件:
DaoMaster
DaoSession
UserDao
@Entity
public class UserBean {
@Id(autoincrement = true)
long id;
@NotNull
String name;
String age;
@Generated(hash = 47803367)
public UserBean(long id, @NotNull String name, String age) {
this.id = id;
this.name = name;
this.age = age;
}
@Generated(hash = 1203313951)
public UserBean() {
}
public long getId() {
return this.id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getAge() {
return this.age;
}
public void setAge(String age) {
this.age = age;
}
}
注解說(shuō)明:
@Id 注解選擇 long / Long 屬性作為實(shí)體ID。在數(shù)據(jù)庫(kù)術(shù)語(yǔ)中,它是主鍵据块。參數(shù)自動(dòng)增量码邻,是使ID值不斷增加(不會(huì)選用舊值)的標(biāo)志折剃。
@Property 讓你定義一個(gè)非默認(rèn)的列名另假,其屬性映射到。如果不存在怕犁,greenDAO將在SQL雜交方式使用字段名(大寫(xiě)边篮,下劃線,而不是駱駝情況下奏甫,例如 customName將成為 CUSTOM_NAME)戈轿。注意:您目前只能使用內(nèi)聯(lián)常量來(lái)指定列名。
@Transient 表明這個(gè)字段不會(huì)被寫(xiě)入數(shù)據(jù)庫(kù)阵子,只是作為一個(gè)普通的java類字段思杯,用來(lái)臨時(shí)存儲(chǔ)數(shù)據(jù)的,不會(huì)被持久化
@Entity 定義實(shí)體
@nameInDb 在數(shù)據(jù)庫(kù)中的名字挠进,如不寫(xiě)則為實(shí)體中類名
@indexes 索引
@schema 指定架構(gòu)名稱為實(shí)體
@active 無(wú)論是更新生成都刷新
@NotNull 不為null
@Unique 唯一約束
@ToMany 一對(duì)多
@OrderBy 排序
@ToOne 一對(duì)一
@Transient 不存儲(chǔ)在數(shù)據(jù)庫(kù)中
@generated 由greendao產(chǎn)生的構(gòu)造函數(shù)或方法
2.構(gòu)建兩個(gè)管理DB的基類
1.BaseDBManager 所有的數(shù)據(jù)庫(kù)操作類都繼承自此
public class BaseDBManager<T, K> {
private AbstractDao<T, K> mDao;
public BaseDBManager(AbstractDao dao) {
this.mDao = dao;
}
public void insert(T item) {
mDao.insert(item);
}
public void insert(T... items) {
mDao.insertInTx(items);
}
public void insert(List<T> items) {
mDao.insertInTx(items);
}
public void insertOrUpdate(T item) {
mDao.insertOrReplace(item);
}
public void insertOrUpdate(T... items) {
mDao.insertOrReplaceInTx(items);
}
public void insertOrUpdate(List<T> items) {
mDao.insertOrReplaceInTx(items);
}
public void deleteByKey(K key) {
mDao.deleteByKey(key);
}
public void delete(T item) {
mDao.delete(item);
}
public void delete(T... items) {
mDao.deleteInTx(items);
}
public void delete(List<T> items) {
mDao.deleteInTx(items);
}
public void deleteAll() {
mDao.deleteAll();
}
public void update(T item) {
mDao.update(item);
}
public void update(T... items) {
mDao.updateInTx(items);
}
public void update(List<T> items) {
mDao.updateInTx(items);
}
/**
* 根據(jù)主鍵查詢數(shù)據(jù) 如果沒(méi)有涉及主鍵 則會(huì)報(bào)錯(cuò)
*
* @param key 主鍵
* @return T
*/
public T query(K key) {
return mDao.load(key);
}
public List<T> queryAll() {
return mDao.loadAll();
}
public List<T> query(String where, String... params) {
return mDao.queryRaw(where, params);
}
public QueryBuilder<T> getQueryBuilder() {
return mDao.queryBuilder();
}
public long count() {
return mDao.count();
}
public void refresh(T item) {
mDao.refresh(item);
}
public void detach(T item) {
mDao.detach(item);
}
}
2.庫(kù)名類
public interface DBConfig {
String DB_NAME = "User.db";
}
3.編寫(xiě)USER庫(kù)的操作類
三個(gè)類分別為
UserDBFactory 用戶數(shù)據(jù)庫(kù)工廠類 通過(guò)這個(gè)類統(tǒng)一下面兩個(gè)類的功能,使用時(shí)調(diào)用這個(gè)類.
UserDBManage 數(shù)據(jù)庫(kù)管理類,用于創(chuàng)建 刪除 關(guān)閉數(shù)據(jù)庫(kù) 獲取session
UserInfoManage 用戶信息管理類 對(duì)用戶列表的增刪改查放這里
public class UserDBFactory {
private static UserDBFactory mInstance = null;
private UserInfoManage userInfoManage;
public static UserDBFactory getInstance() {
if (mInstance == null) {
synchronized (UserDBFactory.class) {
if (mInstance == null) {
mInstance = new UserDBFactory();
}
}
}
return mInstance;
}
public UserInfoManage getUserInfoManage() {
if (userInfoManage == null) {
userInfoManage = new UserInfoManage(UserDBManage.getInstance(MyApplication.getApplication()).getDaoSession().getUserBeanDao());
}
return userInfoManage;
}
}
public class UserDBManage {
private static UserDBManage dbManage;
private Context context;
public static UserDBManage getInstance(Context context) {
if (dbManage == null) {
synchronized (UserDBManage.class) {
if (dbManage == null) {
dbManage = new UserDBManage(context);
}
}
}
return dbManage;
}
private UserDBManage(Context context) {
this.context = context;
}
private DaoMaster.DevOpenHelper mHelper;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
/**
* 獲取DaoSession * * @return
*/
public synchronized DaoSession getDaoSession() {
if (null == mDaoSession) {
mDaoSession = getDaoMaster().newSession();
}
return mDaoSession;
}
/**
* 關(guān)閉數(shù)據(jù)庫(kù)
*/
public synchronized void closeDataBase() {
closeHelper();
closeDaoSession();
}
/**
* 判斷數(shù)據(jù)庫(kù)是否存在色乾,如果不存在則創(chuàng)建 * * @return
*/
private DaoMaster getDaoMaster() {
if (null == mDaoMaster) {
mHelper = new DaoMaster.DevOpenHelper(context, DBConfig.DB_NAME, null);
mDaoMaster = new DaoMaster(mHelper.getWritableDb());
}
return mDaoMaster;
}
private void closeDaoSession() {
if (null != mDaoSession) {
mDaoSession.clear();
mDaoSession = null;
}
}
private void closeHelper() {
if (mHelper != null) {
mHelper.close();
mHelper = null;
}
}
}
/**
* Describe:DB操作類
*/
public class UserInfoManage extends BaseDBManager<UserBean, String> {
public UserInfoManage(AbstractDao dao) {
super(dao);
}
}
五.增刪改查功能實(shí)現(xiàn)
1.布局和代碼目錄展示
布局和條目布局代碼我就不寫(xiě)在這里了,各位自行定義.列表使用的是recyclerview;
2.自定義適配器
package com.maomao.technology.greendaodemo;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.TextView;
import java.util.List;
/**
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* 創(chuàng)建日期:2019/4/19 on 15:45
* 作 者:劉喵喵
* 郵 箱:915850672@qq.com
* 描 述:
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
public class MyAdapter extends RecyclerView.Adapter {
private final int mLayoutId;
private final List<UserBean> mData;
private final Context mContext;
private final LayoutInflater inflater;
public MyAdapter(List<UserBean> mData, int mLayoutId, Context mContext) {
this.mData = mData;
this.mLayoutId = mLayoutId;
this.mContext = mContext;
inflater = LayoutInflater.from(mContext);
}
@NonNull
@Override
public RecyclerView.ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int i) {
View view = inflater.inflate(mLayoutId, parent, false);
return new MyViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
MyViewHolder holder = (MyViewHolder) viewHolder;
holder.key.setText(mData.get(i).getId()+"");
holder.name.setText(mData.get(i).getName()+"");
holder.age.setText(mData.get(i).getAge()+"");
}
@Override
public int getItemCount() {
return mData.size();
}
public class MyViewHolder extends RecyclerView.ViewHolder {
private final TextView age;
private final TextView name;
private final TextView key;
public MyViewHolder(View v) {
super(v);
name = v.findViewById(R.id.name);
age = v.findViewById(R.id.age);
key = v.findViewById(R.id.key);
}
}
}
3.主要功能邏輯
public class MainActivity extends Activity implements View.OnClickListener {
private UserInfoManage userInfoManage;
private List<UserBean> userBeanList = new ArrayList<>();
private RecyclerView recyclerView;
private MyAdapter myAdapter;
private EditText keyEdit;
private EditText valueEdit;
private TextView add;
private TextView delete;
private TextView search;
private TextView show;
private TextView update;
private UserBean userBean;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initview();
initdata();
UserDBFactory userDBFactory = new UserDBFactory();
userInfoManage = userDBFactory.getUserInfoManage();
}
private void initdata() {
myAdapter = new MyAdapter(userBeanList, R.layout.user_item, this);
recyclerView.setAdapter(myAdapter);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
}
private void initview() {
add = findViewById(R.id.add_btn);
delete = findViewById(R.id.delete_btn);
search = findViewById(R.id.search_btn);
show = findViewById(R.id.show_btn);
recyclerView = findViewById(R.id.recyclerView);
keyEdit = findViewById(R.id.key_edt);
valueEdit = findViewById(R.id.value_edt);
update = findViewById(R.id.update_btn);
add.setOnClickListener(this);
delete.setOnClickListener(this);
search.setOnClickListener(this);
show.setOnClickListener(this);
update.setOnClickListener(this);
}
@Override
public void onClick(View v) {
Random mRandom = new Random();
String key = keyEdit.getText().toString();
switch (v.getId()) {
case R.id.add_btn:
//添加數(shù)據(jù)
for (int i = 0; i < 10; i++) {
userBean = new UserBean();
userBean.setId(i + "");
int age = mRandom.nextInt(10) + 10;
userBean.setAge(age + "");
userBean.setName("瑤瑤" + i);
userInfoManage.insertOrUpdate(userBean);//插入或替換
}
myAdapter.notifyDataSetChanged();
//顯示
show.performClick();
break;
case R.id.delete_btn:
//刪除key為..的數(shù)據(jù)
userInfoManage.deleteByKey(key);
show.performClick();
break;
case R.id.show_btn:
userBeanList.clear();
//查詢所有并顯示
List<UserBean> userBeans = userInfoManage.queryAll();
userBeanList.addAll(userBeans);
myAdapter.notifyDataSetChanged();
break;
case R.id.search_btn:
//搜索key為..的數(shù)據(jù)
UserBean query = userInfoManage.query(key);
if (query != null) {
userBeanList.clear();
userBeanList.add(query);
myAdapter.notifyDataSetChanged();
} else {
Toast.makeText(this, "沒(méi)有該條數(shù)據(jù)", Toast.LENGTH_SHORT).show();
}
break;
case R.id.update_btn:
//使用主鍵查詢需要修改的數(shù)據(jù)
UserBean userBean = userInfoManage.query(key);
if (userBean != null) {
userBean.setName(valueEdit.getText().toString());
//修改
userInfoManage.update(userBean);
show.performClick();
} else {
Toast.makeText(this, "沒(méi)有該條數(shù)據(jù)", Toast.LENGTH_SHORT).show();
}
break;
}
}
}
4.全局context
public class MyApplication extends Application {
//全局唯一的context
private static MyApplication application;
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
application = this;
}
public static Context getContext() {
return application;
}
@Override
public void onCreate() {
super.onCreate();
}
/**
* 獲取全局唯一上下文
*
* @return BaseApplication
*/
public static MyApplication getApplication() {
return application;
}
}
最后再放一次我的Demo鏈接
https://github.com/liumaomao0209/GreenDaoDemo
官方網(wǎng)站:http://greendao-orm.com/