【代码是最好的老师】
1.概述
GreenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 框架
greendao具有以下优点,是项目架构期db方案的首选:
- 存取速度快
- 支持加密
- 轻量、api极简
- 支持缓存
- 中间代码自动生成,代码编写量小
- 【重点】开源至今,经历千锤百炼,稳定可靠
2.使用
总体分为三步:
- 配置导包
- 编写实体类(设计表)
- 编写CRUD工具类
- 调用封装的CRUD方法
本次采用得是组件化,使数据库有关的代码独立在一个module中,在APP module中调用。规范化开发,方便后续直接引入db_greendao库。
2.1 配置
step1、step2:
在项目根build.gradle中配置仓库源及插件
//greendao_step1: add repository
mavenCentral()
//greendao_step2: add plugin
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0'
如:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
//greendao_step1: add repository
mavenCentral()
}
dependencies {
classpath "com.android.tools.build:gradle:4.0.2"
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0' //greendao_step2: add plugin
}
}
allprojects {
repositories {
google()
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
2.2 应用插件&导包
step3、step4、step5、step6:
gradle配置:应用插件、导包、配置greendao中间代码生成路径
//greendao_step3: apply plugin
apply plugin: 'org.greenrobot.greendao'
//greendao_step4: add library
implementation 'org.greenrobot:greendao:3.3.0'
//greendao_step5:
//GreenDao 3.0+采用注解的方式来定义实体类,通过gradle插件生成相应的代码
greendao {
schemaVersion 1
daoPackage 'com.cupster.func_db_greendao.auto'//建议同一包名下
targetGenDir 'src/main/java'
}
如:
apply plugin: 'com.android.application'
//greendao_step3:
apply plugin: 'org.greenrobot.greendao'
android {
...
}
//greendao_step4:
//GreenDao 3.0+采用注解的方式来定义实体类,通过gradle插件生成相应的代码
greendao {
schemaVersion 1
daoPackage 'com.cupster.func_db_greendao.auto'//建议同一包名下
targetGenDir 'src/main/java'
}
dependencies {
implementation fileTree(dir: "libs", include: ["*.jar"])
implementation 'androidx.appcompat:appcompat:1.1.0'
implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
//greendao_step5: add library
implementation 'org.greenrobot:greendao:3.3.0'
}
2.3 混淆
step6:
# greendao_step6:
# greendao 3.3.0 proguard
#======================================================================
-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {
public static java.lang.String TABLENAME;
}
-keep class **$Properties { *; }
# If you DO use SQLCipher:
-keep class org.greenrobot.greendao.database.SqlCipherEncryptedHelper { *; }
# If you do NOT use SQLCipher:
-dontwarn net.sqlcipher.database.**
# If you do NOT use RxJava:
-dontwarn rx.**
#======================================================================
2.4 编写实体类(设计表)
step7:
编写实体类,根据需求加上响应注解,build project编译一下项目,就会自动生成中间代码。
在此之前需要简单了解一些基础的注解:
注解 | 作用 |
---|---|
@Entity | 声明当前实体类为greendao实体类,相当于数据库中的表 |
@Id | @Id(autoincrement = true) 设置主键,自增长Id |
@NotNull | 声明该字段在数据库不能为空 NOT NULL |
@Entity
public class User {
@Id(autoincrement = true)
private Long _id;
private int dr;
private String headUrl;
private String obj;
@NotNull
private String name;
private String auth_token;
@NotNull
private String account;
@NotNull
private String password;
2.5编写DaoManager
step8:
build project之后,会在目标文件夹,生成DaoMaster、DaoSession、XxxDao中间代码。
其中的意义如下:
类 | 作用 |
---|---|
DaoMaster | DaoMaster保存数据库对象,代表着一个数据库的连接,内部有SQLiteOpenHelper实现 |
DaoSession | 为实体提供了一些通用的持久性方法,如CURD |
XxxDAO | [表名Dao]数据库表的访问对象,拥有基本的CURD及统计类等高级方法 |
使用之前,需要我们先编写DaoManager,封装数据库的创建、表创建、增删改查,以及数据库的升级等
//greendao_step8:编写dao管理类
public class DaoManager {
private static final String TAG = "DaoManager";
public static final String DB_NAME ="demo_db";
public static boolean SHOW_LOG = false;
private Context mContext;
private volatile static DaoManager mDaoManager = null;
private static DaoMaster mDaoMaster = null;
private static DaoMaster.DevOpenHelper mDaoMasterHelper = null;
private static DaoSession mDaoSession ;
public static DaoManager getInstance(Context appContext){
if (mDaoManager == null){
mDaoManager = new DaoManager(appContext);
}
return mDaoManager;
}
private DaoManager(Context context){
mContext = context;
}
public DaoMaster getDaoMaster(){
if (mDaoMaster == null){
mDaoMasterHelper = new DaoMaster.DevOpenHelper(mContext ,DB_NAME ,null);
mDaoMaster = new DaoMaster(mDaoMasterHelper.getWritableDb());
}
return mDaoMaster;
}
public DaoSession getDaoSession(){
if (mDaoSession == null){
if (mDaoMaster == null ){
getDaoMaster();
}
mDaoSession = mDaoMaster.newSession();
}
return mDaoSession;
}
public void debug(){
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
SHOW_LOG = true;
}
public void closeConnection(){
closeHelper();
clearDaoSession();
}
private void closeHelper() {
if (mDaoMasterHelper != null){
mDaoMasterHelper.close();
mDaoMasterHelper = null;
}
}
private void clearDaoSession() {
if (mDaoSession != null){
mDaoSession.clear();
mDaoSession = null;
}
}
}
2.6编写XxxDaoHelper
编写操作封装类XxxDaoHelper,用于完成具体的CRUD、count、条件查询操作、原始sql语句查询等
以用户表为例:
package com.cupster.func_db_greendao.crud;
import android.content.Context;
import android.util.Log;
import com.cupster.func_db_greendao.DaoManager;
import com.cupster.func_db_greendao.auto.UserDao;
import com.cupster.func_db_greendao.entity.User;
import org.greenrobot.greendao.query.QueryBuilder;
import java.util.List;
public class UserDaoHelper {
private static final String TAG = "UserDaoHelper";
private DaoManager mManager;
public UserDaoHelper(Context appContext){
mManager = DaoManager.getInstance( appContext );
}
/**
* 单条插入
* @param user
* @return
*/
public boolean insert(User user){
boolean result = mManager.getDaoSession().getUserDao().insert(user) != -1;
if (DaoManager.SHOW_LOG){
Log.d(TAG, "insert: " + result +" ==> "+ user.toString());
}
return result;
}
/**
* 多条item插入
* @param userList
* @return boolean结果
*/
public boolean insertMulti(final List<User> userList){
boolean result = false;
try {
mManager.getDaoSession().runInTx(new Runnable() {
@Override
public void run() {
for (User user : userList){
long add_id = mManager.getDaoSession().insertOrReplace(user) ;
if (DaoManager.SHOW_LOG){
Log.d(TAG, "insert items : " + add_id +" ==> "+ user.toString());
}
}
}
});
}catch (Exception e){
e.printStackTrace();
}
return result;
}
public boolean update(User user){
boolean result = false;
try {
mManager.getDaoSession().update(user);
result = true;
}catch (Exception e){
e.printStackTrace();
}
if (DaoManager.SHOW_LOG){
Log.d(TAG, "update: " + result +" ==> "+ user.toString());
}
return result;
}
public boolean delete(User user){
boolean result = false;
try {
mManager.getDaoSession().delete(user);
result = true;
}catch (Exception e ){e.printStackTrace();}
if (DaoManager.SHOW_LOG){
Log.d(TAG, "delete: " + result +" ==> "+ user.toString());
}
return result;
}
public boolean deleteAll(){
boolean result = false;
try {
mManager.getDaoSession().deleteAll(User.class);
result = true;
}catch (Exception e ){
e.printStackTrace();
}
if (DaoManager.SHOW_LOG){
Log.d(TAG, "delete all : " + result );
}
return result;
}
public List <User> queryAll (){
return mManager.getDaoSession().loadAll(User.class);
}
public User queryById(long _id){
return mManager.getDaoSession().load(User.class ,_id);
}
public List<User> queryBySQL(String sql , String[] conditions){
return mManager.getDaoSession().queryRaw(User.class ,sql ,conditions);
}
/**
* 使用queryBuilder 条件查询
* @return
*/
public List<User> queryByQueryBuilder(long id){
QueryBuilder<User> queryBuilder = mManager.getDaoSession().queryBuilder(User.class);
return queryBuilder.where(UserDao.Properties._id.eq(id)).list();
}
/**
* 使用queryBuilder 条件查询
* @return
*/
public List<User> queryByQueryBuilder(String account){
QueryBuilder<User> queryBuilder = mManager.getDaoSession().queryBuilder(User.class);
return queryBuilder.where(UserDao.Properties.Account.eq(account)).list();
}
/**
*
* @param isDelete 0=false 1=true
* @return
*/
public List<User> queryByQueryBuilder(int isDelete){
QueryBuilder<User> queryBuilder = mManager.getDaoSession().queryBuilder(User.class);
return queryBuilder.where(UserDao.Properties.Dr.eq(isDelete)).list();
}
}
至此,我们已经完成了具体表的操作封装。
3. 具体使用
实际结果:
初始代码:
TextView mTvShow;
UserDaoHelper mUserDaoHelper;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.btn_add_item).setOnClickListener(this);
...
mTvShow = findViewById(R.id.tv_show);
mUserDaoHelper = new UserDaoHelper(getApplicationContext());
}
3.1增删改查-增 Insert
基于以上代码,进行单条数据插入:
User user = new User();
user.setAccount("18960222222");
user.setName("Cupster");
user.setPassword("Cupster@163.com");
if (mUserDaoHelper.insert(user)){
Toast.makeText(this ,"已添加",Toast.LENGTH_SHORT).show();
}
list数据插入:
```java List list = new ArrayList<>(); User user1 = new User(); user1.setAccount("18960333333"); user1.setName("CupsterXX"); user1.setPassword("Cupster@163.com"); User user2 = new User(); user2.setAccount("18960444444"); user2.setName("Div"); user2.setDr(1); user2.setPassword("Cupster2@163.com"); User user3 = new User(); user3.setAccount("18960555555"); user3.setName("Higloo"); user3.setPassword("Cupster3@163.com"); list.add(user1); list.add(user2); list.add(user3); if (mUserDaoHelper.insertMulti(list)){ Toast.makeText(this ,"已添加",Toast.LENGTH_SHORT).show(); } ```3.2增删改查-删 Delete
删除所有
if (mUserDaoHelper.deleteAll()){
Toast.makeText(this ,"已删除",Toast.LENGTH_SHORT).show();
}
删除指定数据
User toDelelte =null;
List <User> queryList = mUserDaoHelper.queryByQueryBuilder("18960222222");
if (queryList != null && queryList.size() > 0 ){
toDelelte = queryList.get(0);
if (mUserDaoHelper.delete(toDelelte)){
Toast.makeText(this ,"已删除",Toast.LENGTH_SHORT).show();
}
}else {
Toast.makeText(this ,"不存在or已删除",Toast.LENGTH_SHORT).show();
}
3.3增删改查-改 Update
修改指定数据
User toUpdate = null;
List <User> queryList2 = mUserDaoHelper.queryByQueryBuilder("18960222222");
if (queryList2 != null && queryList2.size() > 0 ){
toUpdate = queryList2.get(0);
toUpdate.setName(toUpdate.getName() +"[改]");
}else {
toUpdate = new User();
toUpdate.setName("Xxx");
toUpdate.setAccount("133333333333");
toUpdate.setPassword("a123456");
}
if (mUserDaoHelper.update(toUpdate)){
Toast.makeText(this ,"已修改",Toast.LENGTH_SHORT).show();
}
3.4增删改查-查 Query
查询所有:
List<User> users = mUserDaoHelper.queryAll();
StringBuilder strBuilder = new StringBuilder();
for (User item : users) {
strBuilder.append("\n");
strBuilder.append(item.get_id());
strBuilder.append("\n");
strBuilder.append(item.getName());
strBuilder.append("\n");
strBuilder.append(item.getAccount());
}
mTvShow.setText(strBuilder.toString());
查询指定id:
User userById = mUserDaoHelper.queryById(1);
StringBuilder strBuilder1 = new StringBuilder();
strBuilder1.append("\n");
strBuilder1.append("查询id=0账户:");
strBuilder1.append("\n");
strBuilder1.append(userById.get_id());
strBuilder1.append("\n");
strBuilder1.append(userById.getName());
strBuilder1.append("\n");
strBuilder1.append(userById.getAccount());
mTvShow.setText(strBuilder1.toString());
sql语句查询:
String sql = "where _id > ?";
String[] condition = new String[]{"0"};
List<User> queryBySQL = mUserDaoHelper.queryBySQL(sql, condition);
StringBuilder strBuilder2 = new StringBuilder();
strBuilder2.append("\n");
strBuilder2.append("查询id>0,账户:");
for (User u : queryBySQL){
strBuilder2.append("\n");
strBuilder2.append(u.get_id());
strBuilder2.append("\n");
strBuilder2.append(u.getName());
strBuilder2.append("\n");
strBuilder2.append(u.getAccount());
}
mTvShow.setText(strBuilder2.toString());
条件查询:
List<User> userByWhereList = mUserDaoHelper.queryByQueryBuilder(1);
StringBuilder strBuilder3 = new StringBuilder();
strBuilder3.append("\n");
strBuilder3.append("查询dr=1,假删除账户:");
for (User u : userByWhereList){
strBuilder3.append("\n");
strBuilder3.append(u.get_id());
strBuilder3.append("\n");
strBuilder3.append(u.getName());
strBuilder3.append("\n");
strBuilder3.append(u.getAccount());
}
mTvShow.setText(strBuilder3.toString());
4.总结
至此,从配置到增删改查已简述完毕,具体代码请参考: