GreenDAO 3.2.2 简单入门(一)增删改查

前言

greenDAO是一款轻巧快捷的Android版ORM,可将对象映射到SQLite数据库。greenDAO针对Android进行了高度优化,性能卓越,占用内存极少。
GreenDAO源码下载

GreenDAO配置

可以点击上述的网址查看GreenDAO最新版本和文档入口,以及如何为本地项目添加依赖。目前,其最新版本是3.2.2。

步骤一

打开Project下的build.gradle,注意不是module下的build.gradle,添加以下内容:

mavenCentral()
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
GreenDAO 3.2.2 简单入门(一)增删改查_第1张图片
GreenDAO配置一.png

步骤二

打开module下的build.gradle,即app/build.gradle,添加以下内容:

apply plugin: 'org.greenrobot.greendao'
implementation 'org.greenrobot:greendao:3.2.2'

GreenDAO 3.2.2 简单入门(一)增删改查_第2张图片
GreenDAO配置二.png

接着 sync now项目。

步骤三

继续在module下的build.gradle中添加配置代码:

// 示例
greendao {
    // value可以根据自身需求更改
    // 数据库版本
    schemaVersion 3
    // 生成DAO、DaoMaster、DaoSeesion的包名
    daoPackage 'com.jwstudio.greendao.gen'
    // 生成DAO、DaoMaster、DaoSeesion的目录
    targetGenDir 'src/main/java'
}

GreenDAO 3.2.2 简单入门(一)增删改查_第3张图片
GreenDAO配置三.png

然后 sync now。如果你没有添加上述配置,在 make project后, XxxDaoDaoMasterDaoSeesion(它们在接下来的内容中会进行简单介绍)会存放在如下图所示的目录下:
GreenDAO 3.2.2 简单入门(一)增删改查_第4张图片
GreenDAO配置四.png

若你添加了上述的配置, make project后你就明白了。注意,目前还不用 make project

准备

下图是demo的目录结构:


GreenDAO 3.2.2 简单入门(一)增删改查_第5张图片
demo目录结构.png

在GreenDAO中,一个实体类就对应的一个表,通过注解的方式关联起来。下面是一些常用注解的介绍。

  • @Entity
    • nameInDb:在数据库中表名,默认是实体类名
    • indexes:为指定的列设置索引,排列时降序还是升序
    • createInDb:是否在数据库中创建数据表,默认为true,即自动创建表
    • active:是否为激活状态,默认为false,非激活状态要通过DAO方法操作
  • @Id:将该属性设置为主键,且该属性为Long型,对应表中的_id主键
    • autoincrement:设置为true表示主键为自动增长
  • @Index:为属性设置索引
    • name:索引名
    • uniquetrue表示唯一索引
  • @Property:设置该属性在数据库表中的列名
    • nameInDb:设置列名
  • @NotNull:非空
  • @Transient:表示此属性时临时存储,不会被存储到表中,即这个属性将不会作为数据表中国的一个字段

新建一个User类,内容 如下:

@Entity(
        nameInDb = "USERS", // 表名
        indexes = {
                @Index(value = "name DESC"), // 为属性name设置索引
        }
)
public class User {
    @Id(autoincrement = true) // 主键,要求是Long型
    private Long id;

    @Index(name = "usercode_index", unique = true) // 设置索引且是唯一索引
    private String usercode;

    @Property(nameInDb = "username") // 设置该属性对应的列名
    @NotNull                         // 非空
    private String name;

    private String userAddress; // 可以为空

    @Transient // 临时存储
    private int tempUserSign;

}

然后make project。成功后User类会多出一些方法,读者不要随意改动就行了。另外,项目下也多出了一个包,也就是之前在module下添加的greendao{}配置的效果,以及相应的类。以下是它们的简单介绍:

  • DaoMaster
    • 是GreenDAO的入口,也是GreenDAO顶级对象
    • 拥有SQLite数据库对象
    • 能够管理DAO类,能够创建和删除表
    • 其内部类OpenHelperDevOpenHelper,是创建SQLite数据库的SQLiteOpenHelper的具体实现
  • DaoSession
    • 管理所有的Dao对象
    • 对实体类进行增删该查等操作
    • 跟踪和管理查询缓存,提高查询效率
  • DAOS(如UserDao类)
    • 能够持久访问和查询实体类
    • DaoSession有更加丰富的增删查改方法

接下来我们来看下UserDao类中一段代码:

UserDao代码片段.png

可以得到,没用注解的属性在表中的列名默认为全大写,如 usercode属性对应 USERCODE;若属性采用驼峰命名法,如 userAddress对应 USER_ADDRESS;若添加了 @Property注解,以 nameInDb属性的值为准。另外,添加了 @Transient注解的属性并没有生成。

UserDao类中还自动生成了创建表的SQL语句,而增删查改的方法定义在其父类AbstractDao中。

假如再新建一个Student的实体类,make project后在com.jwstudio.greendao.gen包下会生成对应的StudentDao类,并且DaoMasterDaoSession也会添加相应的代码,即有多少个实体类,经过make project后就有DAO类与之对应。

创建HMROpenHelper类,代码如下:

public class HMROpenHelper extends DaoMaster.OpenHelper {
    public HMROpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }
}

创建MyGreenDAOApplication类,并在AndroidManifest.xml中的application标签下添加android:name属性,android:name=".MyGreenDAOApplication",其代码如下:

public class MyGreenDAOApplication extends Application {

    private SQLiteDatabase db;
    private DaoMaster mDaoMaster;
    private DaoSession mDaoSession;
    public static MyGreenDAOApplication instances;

    @Override
    public void onCreate() {
        super.onCreate();
        instances = this;
        setDatabase();
    }

   // GreenDAO各应用对象的初始化
    private void setDatabase() {
        // 创建数据库
        HMROpenHelper mHelper = new HMROpenHelper(this, "myGDDb", null);
        db = mHelper.getWritableDatabase();
        mDaoMaster = new DaoMaster(db);
        mDaoSession = mDaoMaster.newSession();
    }

    public static MyGreenDAOApplication getInstances() {
        return instances;
    }

    public SQLiteDatabase getDb() {
        return db;
    }

    public DaoMaster getmDaoMaster() {
        return mDaoMaster;
    }

    public DaoSession getmDaoSession() {
        return mDaoSession;
    }
}

初始化

public class MainActivity extends AppCompatActivity {

    private UserDao userDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 获取UserDao对象
        userDao = MyGreenDAOApplication.getInstances().getmDaoSession().getUserDao();
    }

    // 打印数据库表中的记录
    private void queryList() {
        String result = "显示结果为:";
        // 获得表中的所有记录
        List users = userDao.loadAll();
        int i = 0;
        for (User user : users) {
            i++;
            String res = result + "i=" + i + ",id:" + user.getId() + ",name:" + user.getName() + ",address:" + user.getUserAddress();
            Log.d("TAG", res);
        }
    }
}

添加记录

  • long insert(T entity):插入指定实体,entity即实体对象
  • void insertInTx(T... entities):插入多个实体,参数可为List集合
  • long insertOrReplace(T entity):插入或替换指定实体
  • void insertOrReplaceInTex(T... entities):插入或替换指定实体,参数可为List集合

单条记录添加

    private void insterOne() {
        User user1 = new User();
        user1.setName("孙悟空");
        user1.setUsercode("001");
        user1.setUserAddress("花果山水帘洞");
        userDao.insert(user1);
    }

    // onCreate()方法的代码更改如下
    userDao.deleteAll();// 删除表中所有记录,保持表中的数据记录纯净,在此便于演示;按需添加
    insterOne();
    queryList() ;

多条记录添加

    private void insertMany() {
        List users = new ArrayList<>();

        User user1 = new User();
        user1.setName("孙悟空");
        user1.setUsercode("001");
        user1.setUserAddress("花果山水帘洞");

        User user2 = new User();
        user2.setName("猪八戒");
        user2.setUsercode("002");
        user2.setUserAddress("高老庄");

        User user3 = new User();
        user3.setName("沙悟净");
        user3.setUsercode("003");
        user3.setUserAddress("流沙河");

        User user4 = new User();
        user4.setName("黑熊怪");
        user4.setUsercode("004");
        user4.setUserAddress("黑风山");

        users.add(user1);
        users.add(user2);
        users.add(user3);
        users.add(user4);

        userDao.insertInTx(users);
    }

    // onCreate()方法的代码更改如下
    userDao.deleteAll();// 保持表中的数据记录纯净,在此便于演示;按需添加
    insterMany();
    queryList() ;

删除

  • void delete(T entity):删除指定的实体
  • void deleteInTx(T... entities):删除多个实体,参数可以是List集合
  • void deleteAll():删除所有记录
  • void deleteByKey(K key):删除指定主键对应的实体
    private void deleteByName(){
        QueryBuilder qb=userDao.queryBuilder();
        // 查询想要删除的记录;根据场景需要,记得判空
        List userList=qb.where(UserDao.Properties.Name.eq("猪八戒")).list();
        for(User user:userList){
            // 每次删除一条记录
            userDao.delete(user);
        }
        // 一次删除多条记录
        // userDao.deleteInTx(userList);
    }

    // onCreate()方法的代码更改如下
    userDao.deleteAll();// 保持表中的数据记录纯净,在此便于演示;按需添加
    insterMany();
    deleteByName();
    queryList() ;

修改

  • void update(T entity):修改一个被查询出来的实体
  • void updateInTx(T... entities):修改多个被查询出来的实体,这些实体可被放在一个List中
    private void updateUser(){
        User user=userDao.queryBuilder().where(UserDao.Properties.Name.eq("孙悟空")).build().unique();
        // 修改使用setter方法
        user.setUserAddress("天宫蟠桃园");
        userDao.update(user);
    }

    // onCreate()方法的代码更改如下
    userDao.deleteAll();// 保持表中的数据记录纯净,在此便于演示;按需添加
    insterMany();
    updateUser();
    queryList() ;

查询

DAO查询

  • java.util.List loadAll:查找所有记录,返回List集合
  • T load(K key):按主键值查询一条记录,返回实体类对象
  • T loadByRowId(long rowId):按行id查询一条记录,返回实体类对象
    注意:
  • 如果主键id是自动增长。则load()方法和loadByRowId()方法作用相同,即key值与rowId值相同
  • list()方法返回所有值,unique()方法返回唯一值
    private void loadOneById() {
        // 要注意”6“是否存在
//        User user = userDao.load(new Long((long) 6));
        User user = userDao.loadByRowId(new Long((long) 6));
        Log.d("TAG", "name:" + user.getName());
    }

    // onCreate()方法的代码更改如下
    userDao.deleteAll();// 保持表中的数据记录纯净,在此便于演示;按需添加
    insterMany();
    loadOneById();

QueryBuilder查询

  • QueryBuilder where(WhereCondition cond, whereCondition... condMore):条件查询,参数之间本质是AND连接
  • QueryBuilder whereOr(WhereCondition cond, whereCondition... condMore):条件查询,参数之间本质是OR连接
  • QueryBuilder distinct():去除重复记录,例如使用联合查询时
  • QueryBuilder limit(int limit):限制记录返回数,用于分页
  • QueryBuilder offset(int offset):偏移结果起始位,即从第几条开始取limit()中限制的记录数,配合limit()使用
  • QueryBuilder orderAsc(Property... properties):升序排列
  • QueryBuilder orderDesc(Property... properties):降序排列
  • WhereCondition and(WhereCondition cond1, WhereCondition cond2, whereCondition... condMore):添加条件,AND连接
  • WhereCondition or(WhereCondition cond1, WhereCondition cond2, whereCondition... condMore):添加条件,OR连接

    private void queryQB() {
        QueryBuilder qb = userDao.queryBuilder();
        // 查询名字带有“悟”字的,并且按照属性usercode进行降序排列
//        List userList=qb.where(UserDao.Properties.Name.like("%悟%"))
//                .orderDesc(UserDao.Properties.Usercode).list();

        //查询名字带有“悟”字的,而且地址时“流沙河”的或者是带有“山”字的且usercode==001的
        List users = qb.where(UserDao.Properties.Name.like("%悟%"),
                qb.or(UserDao.Properties.UserAddress.eq("流沙河"),
                        qb.and(UserDao.Properties.UserAddress.like("%山%"),
                                UserDao.Properties.Usercode.eq("001")))).list();

        if (users != null) {
            int i = 0;
            for (User user : users) {
                i++;
                String res = "i=" + i + ",id:" + user.getId() + ",name:" + user.getName() + ",address:" + user.getUserAddress();
                Log.d("TAG", res);
            }
        }
    }

   // 按名字查询
   private void queryOneByName() {
        User user = userDao.queryBuilder().where(UserDao.Properties.Name.eq("孙悟空")).build().unique();
        if (user != null) {
            tvResult.setText("添加一条记录:id:" + user.getId() + ",地址:" + user.getUserAddress());
        }
    }

    // 分页示例
    // limit(3):查询3条记录,offset(1):从第2条记录开始,0表示从第一条记录开始
    // 可用于分页,即limit(3)表示一页有3条记录,可用于显示一页的记录
    List users = userDao.queryBuilder().limit(3).offset(1).list();

Query重复查询

  • Query build():获得Query对象
  • Query setParameter(int index, java.lang.Object parameter):设置查询参数
    private void queryRepeat(){
        Query query=userDao.queryBuilder().where(UserDao.Properties.Name.like("%悟%"),
                UserDao.Properties.UserAddress.like("%山%")).build();

        // 重新设置参数
        query.setParameter(0,"%怪%");
        query.setParameter(1,"%洞%");
        List userList=query.list();
    }

SQL查询

  • java.util.List queryRaw(java.lang.String where, java.lang.String... selectionArg):直接用sql语句获得查询List对象
  • Query queryRawCreate((java.lang.String where, java.lang.Object... selectionArg):获得Query对象,Query.list()获得List对象
    注意:sql语句中的列名是数据表列名,而不是实体类的属性名。
    private void querySql(){
//        List userList=userDao.queryRaw("where  username like '%悟%'");
        Query query=userDao.queryRawCreate("where  username like '%悟%'");
        List userList=query.list();
        queryView(userList);
    }

补充

  • eq:==(等于)
  • notEq:!=(不等于)
  • gt:>(大于)
  • It:<(小于)
  • ge:>=(大于等于)
  • le:<=(小于等于)
  • like:包含,需要与%(_)配合使用
  • between:在两者之间
  • in:在某些值内
  • notIn:不在某些值内

注意:在代码中加入以下两行代码,即可在Android Monitor窗口中看到生成的sql语句,以及sql语句中的值。

// 在onCreate()中添加
QueryBuilder.LOG_SQL = true;        // 显示sql语句
QueryBuilder.LOG_VALUES = true; // 显示sql语句中的值

总结

拥有SQL基础,有利于理解GreenDAO的API,也能更好地运用。在增删改查中,查询是最复杂的,毕竟在开发中查询时用的最多的,也是最难用的,需要多动手实战才能掌握。

最终源码
GreenDAO 3.2.2 简单入门(二)多表查询和多表关联
GreenDAO 3.2.2 简单入门(三)数据库升级

你可能感兴趣的:(GreenDAO 3.2.2 简单入门(一)增删改查)