Android数据库框架-GreenDao入门

Android数据库框架-GreenDao入门

[0] greenDAO介绍

GreenDAO是一款开源且面向Android的轻便、快捷的ORM框架,可以将对象映射到SQLite数据库中.它针对Android进行了高度优化,性能最大化且内存消耗极少同时还支持数据库加密.[百科]

一、greendao环境配置

1.新建一个项目

我的项目名称为Search

2.配置
2.1在项目Project的build.gradle中配置classpath:
buildscript {
    repositories {
        google()
        jcenter()
        
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:3.5.2'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'//添加插件
        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

之后点击Sync Project

2.2. 在app的build.gradle中配置
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao'

之后在dependencies中添加依赖

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
    implementation 'org.greenrobot:greendao:3.2.2' // 添加依赖
}

之后配置数据库相关信息

greendao {
    schemaVersion 1 //当前数据库版本
    targetGendir 'src/main/java'//指定生成代码的目录
    daoPackage 'com.lab.search'//生成代码到具体的包下
}

配置就完成了,之后点击Sync Now

在Sync时,出现了下载依赖很慢的事情,所以我在工程目录下的build.gradle将buildscript的repositories改成了

repositories {
        google()
        //jcenter()
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
        
    }

以及

allprojects {
    repositories {
        google()
        //jcenter()
        maven{ url 'http://maven.aliyun.com/nexus/content/groups/public/'}
    }
}

把地址改成了阿里云的仓库,下载就快了。

二、使用greendao(1)

2.1. 创建一个实体类

在目录下创建一个Package名为bean,在bean包下面创建一个Java类,类为实体类,即仅有属性以及getter、setter、构造方法以及toString()方法的类,一个实体类则对应一张数据库的表,我将这个实体类取名为UserInfo,类中有id,userName,phoneNumber,address等属性

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Property;

@Entity
public class UserInfo {
    @Id
    private Long id;

    @Property(nameInDb = "user_name")
    private String userName;

    @Property(nameInDb = "phone_number")
    private String phoneNumber;

    @Property(nameInDb = "address")
    private String address;
}

在这里,我用了许多注解,而这些注解有什么作用呢?简单介绍一下在GreenDao中常用的一些注解

@Entity:将我们的java普通类变为一个能够被greenDAO识别的数据库类型的实体类,也就是将这个类标记为要映射到数据库的实体类
@Id:主键,选择使用long或Long,若写成@Id(autoincrement = true)则可标记为自增长。
@Property(nameInDb = “”) :表示该类的这个属性是表的一个字段(即一列),且非主键,nameInDb值则是这个字段的名字,
@NotNull: 不为null
@Transient 不保存于数据库,添加此标记后不会生成数据库表的列
@Index 作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束
@Unique: 唯一约束,也就是值必须唯一
@ToOne 表为一对一关系
@ToMany 一对多关系
@Generated 由greendao产生的构造函数或方法,此注释标记的所有代码元素都可以在生成的下一次运行中更改/删除

编译(Make Project)之后,代码就自动生成了构造函数及set get方法,之后再加上toString方法,在进行数据库操作时,可用toString()方法打印来验证结果的正确性。

@Entity
public class UserInfo {
    @Id
    private long id;

    @Property(nameInDb = "user_name")
    private String userName;

    @Property(nameInDb = "phone_number")
    private String phoneNumber;

    @Property(nameInDb = "address")
    private String address;

    @Generated(hash = 459973421)
    public UserInfo(long id, String userName, String phoneNumber, String address) {
        this.id = id;
        this.userName = userName;
        this.phoneNumber = phoneNumber;
        this.address = address;
    }

    @Generated(hash = 1279772520)
    public UserInfo() {
    }

    public long getId() {
        return this.id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getUserName() {
        return this.userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPhoneNumber() {
        return this.phoneNumber;
    }

    public void setPhoneNumber(String phoneNumber) {
        this.phoneNumber = phoneNumber;
    }

    public String getAddress() {
        return this.address;
    }

    public void setAddress(String address) {
        this.address = address;
    }
    @Override
    public String toString() {
        return "UserInfo{" +
                "id=" + id +
                ", userName='" + userName + '\'' +
                ", phoneNumber='" + phoneNumber + '\'' +
                ", address='" + address + '\'' +
                '}';
    }
}
2.2. 查看UserInfoDAO,DaoMaster及DaoSession

上述操作结束之后,在工程目录下,GreenDAO的生成目录中可以找到相应的数据库操作类,我实体类UserInfo的操作类名称为UserInfoDAO,同时也会自动生成DaoMaster和DaoSession
在这里插入图片描述
可以看到生成了三个文件,一个是实体类的操作类,还有DaoMaster,DaoSession等类。
我们先看看DaoMaster类,DaoMaster类主要定义了几个函数
(1)createAllTables、dropAllTables

/** Creates underlying database table using DAOs. */
    public static void createAllTables(Database db, boolean ifNotExists) {
        UserInfoDao.createTable(db, ifNotExists);
    }

    /** Drops underlying database table using DAOs. */
    public static void dropAllTables(Database db, boolean ifExists) {
        UserInfoDao.dropTable(db, ifExists);
    }

这两个方法表明了DaoMaster的两个作用,创建和删除所有表。
(2)newSession

public DaoSession newSession() {
	return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}

public DaoSession newSession(IdentityScopeType type) {
	return new DaoSession(db, type, daoConfigMap);
}

这两个类可以创建Session绘画,有两种重载形式,一种可以让我们自定义类型。
(3)构造函数

public DaoMaster(SQLiteDatabase db) {
        this(new StandardDatabase(db));
    }

    public DaoMaster(Database db) {
        super(db, SCHEMA_VERSION);
        registerDaoClass(UserInfoDao.class);
    }

两个重载形式,一个时生成一个数据库,另一个则是注册Config,查看一下registerDaoClass类则会发现,daoConfigMap是一个Map结构

protected final Map<Class<? extends AbstractDao<?, ?>>, DaoConfig> daoConfigMap;
protected void registerDaoClass(Class<? extends AbstractDao<?, ?>> daoClass) {
        DaoConfig daoConfig = new DaoConfig(db, daoClass);
        daoConfigMap.put(daoClass, daoConfig);
    }

通过传进来的UserInfoDao.class作为key,对这个daoConfig进行绑定操作。
而进入到DaoConfig类中,查看DaoConfig的源码时,可以看到注释中的介绍

/**
 * Internal class used by greenDAO. DaoConfig stores essential data for DAOs, and is hold by AbstractDaoMaster. This
 * class will retrieve the required information from the DAO classes.
 */

DaoConfig存储DAO的基本数据,并由AbstractDaoMaster所持有。 该类将从DAO类中检索所需的信息。即将DAO类作为key来检索信息

而DaoSession类则主要是用来操作DAO对象的,它有三个方法
(1)构造函数

public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
            daoConfigMap) {
        super(db);

        userInfoDaoConfig = daoConfigMap.get(UserInfoDao.class).clone();
        userInfoDaoConfig.initIdentityScope(type);

        userInfoDao = new UserInfoDao(userInfoDaoConfig, this);

        registerDao(UserInfo.class, userInfoDao);
    }

从代码中我们可以看到,构造函数做了这么几件事儿
1.取出map中对应DAO的daoConfig
2.初始化缓存类型
3.根据配置可以得到一个DAO对象
4.将DAO对象进行注册,也是通过Map进行管理
(2)getUserInfoDao方法

public UserInfoDao getUserInfoDao() {
        return userInfoDao;
    }

可返回dao对象,说明可以返回dao对象并对其进行具体的操作了。
(3)clear函数

public void clear() {
   	userInfoDaoConfig.clearIdentityScope();
}

clear函数就是清楚缓存的函数, clearIdentityScope()

2.3编写DaoManage类

其实,上面操作过后,可以直接进行数据库的使用了,但是这里仍然编写了一个DaoManage类,希望在使用过程中更方便的进行初始化工作
主要内容就是进行各种变量的初始化之后,获得数据库,获取DaoSession对象好对表进行数据操作。
代码如下:

public class DaoManage {
    private Context mContext;

    //数据库的名称
    private static final String DB_NAME = "user.db";

    //多线程中要被共享的要用volatile修饰,Greendao管理类
    private volatile static DaoManage mInstance;

    //DAOMaster 保存数据库对象
    private static DaoMaster mDaoMaster;

    //Helper类
    private static DaoMaster.DevOpenHelper mHelper;

    //Dao对象中的增删改查的对象
    private static DaoSession mDaoSession;

    private DaoManage(){

    }

    //使用单例模式来获取GreenDao管理类的对象,即操作数据库的对象
    public static DaoManage getInstance(){
        if (mInstance == null){
            synchronized (DaoManage.class){
                if(mInstance == null){
                    mInstance = new DaoManage();
                }
            }
        }
        return mInstance;
    }

    //初始化上下文
    public void init(Context context){
        this.mContext = context;
    }

    //创建(若没有)并获取数据库
    public DaoMaster getDaoMaster(){
        if(mDaoMaster == null){
            //创建一个数据库
            mHelper = new DaoMaster.DevOpenHelper(mContext, DB_NAME, null);
            mDaoMaster = new DaoMaster(mHelper.getWritableDatabase());
        }
        return mDaoMaster;
    }

    //获取DaoSession对象,完成增删改查操作
    public DaoSession getDaoSession(){
        if(null == mDaoSession){
            //若表为空,new一个
            if(null == mDaoMaster){
                //若数据库为空,则创建数据库
                mDaoMaster = getDaoMaster();
            }
            mDaoSession = mDaoMaster.newSession();
        }
        return mDaoSession;
    }

    //关闭连接
    public void closeConnection(){
        if(mHelper != null){
            mHelper.close();
            mHelper = null;
        }
        if(mDaoSession != null){
            mDaoSession.clear();
            mDaoSession = null;
        }
    }
}

三、GreenDao使用(2)

3.1. 编写DBHelper类

实际上,GreenDao的数据库操作已经十分简便,我们是可以直接进行使用的,但是为了更加整洁的使用,我还是将增删改查的操作进行了封装,写在了DBHelper类中

(0)加入UserInfoDao对象属性并初始化
private UserInfoDao userInfoDao = DaoManage.getInstance().getDaoSession().getUserInfoDao(); 
(1)按id查找数据
//查找(按id查找)
public UserInfo queryById(Long id){
    List<UserInfo> list = userInfoDao.queryBuilder().where(UserInfoDao.Properties.Id.eq(id)).build().list();
    UserInfo userInfo = list.isEmpty() ? null : list.get(0);
    return userInfo;
}
(2)查找全部
//查找全部
public List<UserInfo> queryAll(){
    return userInfoDao.queryBuilder().build().list();
}

查询还可以批量查询,多条件查询,模糊搜索等等内容,由于太多,就不全部列出来了,可以查阅相关文档按照需要进行使用。

(3)增
//增加
public void add(UserInfo userInfo){
    if (queryById(userInfo.getId()) == null){
        userInfoDao.insert(userInfo);
    }else{
        userInfoDao.update(userInfo);
    }
}
//批量增加
public void add(List<UserInfo> userInfoList){
    userInfoDao.insertInTx(userInfoList);
}
(4)删
//删除一个对象
public void delete(UserInfo userInfo){
    userInfoDao.delete(userInfo);
}
//删除一个列表的对象
public void deleteByList(List<UserInfo> userInfoList){
    userInfoDao.deleteInTx(userInfoList);
}
//按主键删除
public void delteByKey(long key){
    userInfoDao.deleteByKey(key);
}
//按主键列表删除
public void deleteByKeyList(List<Long> idList){
    userInfoDao.deleteByKeyInTx(idList);
}
//删除所有
public void deleteAll(){
    userInfoDao.deleteAll();
}
(5)改
//修改
public boolean update(UserInfo userInfo){
      UserInfo findUser = userInfoDao.queryBuilder().where(UserInfoDao.Properties.Id.eq(userInfo)).build().unique();
      if (findUser != null){
          userInfoDao.update(userInfo);
          return true;
      }else{
          return false;
      }
}
3.2.在MainActivity中进行使用

在Android6.0之后,我们需要在代码中先对权限进行检查,即检查有没有文件的读写权限,如果没有权限,要申请权限,所以在onCreate()函数中,在前面要先加入一段代码:

//检查当前权限,如果没有,申请request,
if(ActivityCompat.checkSelfPermission(this,Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED
	|| ActivityCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED){
    //申请一个或多个权限
    ActivityCompat.requestPermissions(MainActivity.this, new String[]{
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE
    }, 100);

}

在类中添加DBHelper类的成员对象,并进行初始化

DBHelper dbHelper = new DBHelper();

之后可以在onCreate()函数中进行使用
先增加一个数据

UserInfo userInfo1 = new UserInfo(null, "laichangping1", "12345678901", "longyan");
dbHelper.add(userInfo1);

进行查找,并查看结果

//查找
List<UserInfo> userInfos = dbHelper.queryAll();
for(UserInfo userInfo : userInfos){
    Log.i("add>>", userInfo.toString());
}

在这里插入图片描述
添加成功
之后,再添加userInfo2和userInfo3,将他们按列表添加,再进行查找

List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(userInfo2);
userInfoList.add(userInfo3);
dbHelper.add(userInfoList);
//查找
List<UserInfo> userInfos = dbHelper.queryAll();
for(UserInfo userInfo : userInfos){
    Log.i("add>>", userInfo.toString());
}

在这里插入图片描述
按主键删除userInfo1并查找

//按主键删除
dbHelper.deleteByKey(userInfo1.getId());
//查找
List<UserInfo> userInfos = dbHelper.queryAll();
for(UserInfo userInfo : userInfos){
    Log.i("add>>", userInfo.toString());
}

在这里插入图片描述
将列表中元素全部删除:

//按列表删除
List<UserInfo> deleteInfos = new ArrayList<>();
deleteInfos.add(userInfo2);
deleteInfos.add(userInfo3);
dbHelper.deleteByList(deleteInfos);
//查找
List<UserInfo> userInfos = dbHelper.queryAll();
for(UserInfo userInfo : userInfos){
    Log.i("add>>", userInfo.toString());
}

在这里插入图片描述
则数据全部被删除干净
同样也可以用Key列表进行删除,效果一样

List<Long> idList = new ArrayList<>();
idList.add(userInfo2.getId());
idList.add(userInfo3.getId());
dbHelper.deleteByKeyList(idList);

接下来新增一条数据并将它进行修改,就添加userInfo1罢,然后将userInfo1改为userInfo2

UserInfo userInfo1 = new UserInfo((long)1,"laichangping1","12345678901", "longyan");
UserInfo userInfo2 = new UserInfo((long)2,"laichangping2","45678912345", "fuzhou");
//添加userInfo1
dbHelper.add(userInfo1);
//查找修改前
List<UserInfo> userInfos1 = dbHelper.queryAll();
for(UserInfo userInfo : userInfos1){
    Log.i("修改前", userInfo.toString());
}
//修改为UserInfo2
userInfo1.setUserName(userInfo2.getUserName());
userInfo1.setAddress(userInfo2.getAddress());
userInfo1.setPhoneNumber(userInfo2.getPhoneNumber());
dbHelper.update(userInfo2);
//查找修改后
List<UserInfo> userInfos2 = dbHelper.queryAll();
for(UserInfo userInfo : userInfos2){
    Log.i("修改后", userInfo.toString());
}

在这里插入图片描述
修改成功

以上就是GreenDao数据库的基本使用方法,本人才疏学浅,也借鉴了不少网上的资料,仅作学习记录之用,如若有误,欢迎各位批评指正

四、总结

GreenDao是一个对Android设计的对象关系映射(ORM)工具,具有很强的性能,并且操作丰富多样,大大降低了编写代码的时间成本,除了上述提到的操作外,还可以自定义sql语句进行数据库操作以及其他的操作。
并且功能也十分强大,通过注解可以自动生成代码,既可以减少代码编写时间,也可以减少代码量。通过调用api函数的形式进行增删改查,也无需重复进行sql语句的编写,节省了时间。本次的实践也受益匪浅。

@author 068赖昌平
原文:原文地址

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值