Android GreenDao数据库高级讲解

上一节讲述了GreenDao数据库的基础讲解:Android GreenDao数据库基础讲解

 

本章节讲述GreenDao数据库的高级讲解

 

 

一.创建实体类后自动生成的Dao类

 

 

public class UserInfoDao extends AbstractDao<UserInfo, Long> {

    public static final String TABLENAME = "USER_INFO";

    /**
     * Properties of entity UserInfo.<br/>
     * Can be used for QueryBuilder and for referencing column names.
     */
    public static class Properties {
        public final static Property Id = new Property(0, Long.class, "id", true, "_id");
        public final static Property Name = new Property(1, String.class, "name", false, "NAME");
        public final static Property Age = new Property(2, String.class, "age", false, "AGE");
    }


    public UserInfoDao(DaoConfig config) {
        super(config);
    }
    
    public UserInfoDao(DaoConfig config, DaoSession daoSession) {
        super(config, daoSession);
    }

    /** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"USER_INFO\" (" + //
                "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
                "\"NAME\" TEXT," + // 1: name
                "\"AGE\" TEXT);"); // 2: age
    }

    /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"USER_INFO\"";
        db.execSQL(sql);
    }

    @Override
    protected final void bindValues(DatabaseStatement stmt, UserInfo entity) {
        stmt.clearBindings();
 
        Long id = entity.getId();
        if (id != null) {
            stmt.bindLong(1, id);
        }
 
        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }
 
        String age = entity.getAge();
        if (age != null) {
            stmt.bindString(3, age);
        }
    }

    @Override
    protected final void bindValues(SQLiteStatement stmt, UserInfo entity) {
        stmt.clearBindings();
 
        Long id = entity.getId();
        if (id != null) {
            stmt.bindLong(1, id);
        }
 
        String name = entity.getName();
        if (name != null) {
            stmt.bindString(2, name);
        }
 
        String age = entity.getAge();
        if (age != null) {
            stmt.bindString(3, age);
        }
    }

    @Override
    public Long readKey(Cursor cursor, int offset) {
        return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
    }    

    @Override
    public UserInfo readEntity(Cursor cursor, int offset) {
        UserInfo entity = new UserInfo( //
            cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
            cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1), // name
            cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2) // age
        );
        return entity;
    }
     
    @Override
    public void readEntity(Cursor cursor, UserInfo entity, int offset) {
        entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
        entity.setName(cursor.isNull(offset + 1) ? null : cursor.getString(offset + 1));
        entity.setAge(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));
     }
    
    @Override
    protected final Long updateKeyAfterInsert(UserInfo entity, long rowId) {
        entity.setId(rowId);
        return rowId;
    }
    
    @Override
    public Long getKey(UserInfo entity) {
        if(entity != null) {
            return entity.getId();
        } else {
            return null;
        }
    }

    @Override
    public boolean hasKey(UserInfo entity) {
        return entity.getId() != null;
    }

    @Override
    protected final boolean isEntityUpdateable() {
        return true;
    }
    
}

从上述代码可以看出,创建实体类后自动创建的Dao其实给我们按照实体类的属性创建了表

 

表名:(实体类类名:UserInfo)

public static final String TABLENAME = "USER_INFO";

 

建表:

/** Creates the underlying database table. */
    public static void createTable(Database db, boolean ifNotExists) {
        String constraint = ifNotExists? "IF NOT EXISTS ": "";
        db.execSQL("CREATE TABLE " + constraint + "\"USER_INFO\" (" + //
                "\"_id\" INTEGER PRIMARY KEY AUTOINCREMENT ," + // 0: id
                "\"NAME\" TEXT," + // 1: name
                "\"AGE\" TEXT);"); // 2: age
    }

 

删表:

 /** Drops the underlying database table. */
    public static void dropTable(Database db, boolean ifExists) {
        String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"USER_INFO\"";
        db.execSQL(sql);
    }

 

实体类属性:

private Long id;//主键 Long型,可以通过@Id(autoincrement = true)设置自增长
private String name;
private String age;

 

由上可知,自动创建的Dao类会根据实体类类名和属性进行创建表,删除表等等操作。

 

 

 

 

 

 

二.注解介绍

 

1.@Entity:用来声明类实体,表示它将映射为数据表 。


@Entity()括号内可加入更详细的设置,如: 


nameInDb =“TABLE_NAME” ——> 声明该表的表名,默认取类名 。


createInDb = true ——> 是否创建表,默认为true。


generateConstructors = true ——> 是否生成含所有参数的构造函数,默认为true。


generateGettersSetters = true ——> 是否生成getter/setter,默认为true。

 

 

 

2.@Id:用来声明某变量为表的主键,类型使用Long 。


@Id()括号可加入autoincrement = true表明自增长。

 

 

 

3.@Unique:用来声明某变量的值需为唯一值。

 

 

 

4.@NotNull:用来声明某变量的值不能为null。

 

 

 

5.@Property 
 

@Property(nameInDb = “URL”) 用来声明某变量在表中的实际字段名为URL。

 

 

6.@Transient:用来声明某变量不被映射到数据表中。

 

 

 

7.@ToOne、@ToMany:用来声明”对一”和“对多”关系。

 

 

 

 

 

 

三.语句讲解

 

1.增

 

插入单条数据

/**
 * 插入一条记录
 */

public void insertUser() {
    //获取实体类
    UserInfo userInfo=new UserInfo();
    userInfo.setId(id);
    userInfo.setName("张三");
    userInfo.setAge("29");
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //插入一条数据
    userInfoDao.insert(userInfo);
}

 

 

插入多条数据

/**
 * 插入多条记录
 */

public void insertUserList() {
    //获取实体类
    UserInfo userInfo1=new UserInfo();
    userInfo1.setId(id);
    userInfo1.setName("张三");
    userInfo1.setAge("29");

    UserInfo userInfo2=new UserInfo();
    userInfo2.setId(id+1);
    userInfo2.setName("李四");
    userInfo2.setAge("39");

    List<UserInfo> list=new ArrayList<>();
    list.add(userInfo1);
    list.add(userInfo2);

    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //插入多条数据
    userInfoDao.insertInTx(list);
}

 

 

 

 

2.插入或替换(插入的数据如果已经存在表中,则替换掉旧数据(根据主键来检测是否已经存在))

 

插入或替换一条数据

/**
 * 插入或替换一条记录
 */

public void insertUser() {
    //获取实体类
    UserInfo userInfo=new UserInfo();
    userInfo.setId(id);
    userInfo.setName("张三");
    userInfo.setAge("29");
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //插入或替换一条数据
    userInfoDao.insertOrReplace(userInfo);
}

 

 

插入或替换多条数据

/**
 * 插入或替换多条记录
 */

public void insertUserList() {
    //获取实体类
    UserInfo userInfo1=new UserInfo();
    userInfo1.setId(id);
    userInfo1.setName("张三");
    userInfo1.setAge("29");

    UserInfo userInfo2=new UserInfo();
    userInfo2.setId(id+1);
    userInfo2.setName("李四");
    userInfo2.setAge("39");

    List<UserInfo> list=new ArrayList<>();
    list.add(userInfo1);
    list.add(userInfo2);

    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //插入或替换多条数据
    userInfoDao.insertOrReplaceInTx(list);
}

 

 

 

 

3.删

 

删除一条数据

/**
 * 删除一条记录
 */

public void deleteUser() {
    //获取实体类
    UserInfo userInfo=new UserInfo();
    userInfo.setId(id);
    userInfo.setName("张三");
    userInfo.setAge("29");
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //删除一条数据
    userInfoDao.delete(userInfo);
}

 

 

删除多条数据

/**
 * 删除多条记录
 */

public void deleteUser() {
    //获取实体类
    UserInfo userInfo1=new UserInfo();
    userInfo1.setId(id);
    userInfo1.setName("张三");
    userInfo1.setAge("29");

    UserInfo userInfo2=new UserInfo();
    userInfo2.setId(id+1);
    userInfo2.setName("李四");
    userInfo2.setAge("39");
        
    List<UserInfo> list=new ArrayList<>();
    list.add(userInfo1);
    list.add(userInfo2);
       
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //删除多条数据
    userInfoDao.deleteInTx(list);
}

 

 

删除全部数据

/**
 * 删除所有记录
 */

public void deleteUser() {
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //删除所有数据
    userInfoDao.deleteAll();
}

 

 

 

 

4.改

 

 

修改一条数据

/**
 * 更新一条记录
 */

public void updateUser() {
    //获取实体类
    UserInfo userInfo=new UserInfo();
    userInfo.setId(id);
    userInfo.setName("张三更新");
    userInfo.setAge("30");
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //更新一条数据
    userInfoDao.update(userInfo);
}

 

 

修改多条数据

/**
 * 更新多条记录
 */

public void updateUser() {
    //获取实体类
    UserInfo userInfo1=new UserInfo();
    userInfo1.setId(id);
    userInfo1.setName("张三更新");
    userInfo1.setAge("30");

    //获取实体类
    UserInfo userInfo2=new UserInfo();
    userInfo2.setId(id+1);
    userInfo2.setName("李四更新");
    userInfo2.setAge("40");
        
    List<UserInfo> list=new ArrayList<>();
    list.add(userInfo1);
    list.add(userInfo2);
        
    //获取相应的Dao
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    //更新多条数据
    userInfoDao.updateInTx(list);
}

 

 

 

5.查

 

<1> 查询全部数据

 

QueryBuilder 查询全部

/**
 * 查询数据列表
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.list();
    return list;
}

 

loadAll 查询全部

/**
 * 查询数据列表
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    List<UserInfo> list = userInfoDao.loadAll();
    return list;
}

 

 

<2> 查询数量

/**
 * 查询数据列表数量
 */

public long queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    long count=userInfoDao.count();
    return count;
 }

 

 

<3> 条件查询

 

精确查询(where)

/**
 * 查询多条数据 姓名=“张三”
*/

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Name.eq("张三")).list();
    return list;
}

 

/**
 * 查询一条数据 姓名=“张三”
 */

public UserInfo queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    UserInfo userInfo = qb.where(UserInfoDao.Properties.Name.eq("张三")).unique();
    return userInfo;
}

 

 

模糊查询(like)

/**
 * 查询数据列表 姓名以“张” 开头
 */

 public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Name.like("张%")).list();
    return list;
}

 

/**
 * 查询数据列表 姓名以“三” 结尾
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Name.like("%三")).list();
    return list;
}

 

区间查询

插入的数据

/**
 * 插入多条记录
 */

public void insertUser() {
    UserInfo userInfo=new UserInfo();
    userInfo.setId(id);
    userInfo.setName("张三");
    userInfo.setAge("30");

    UserInfo userInfo1=new UserInfo();
    userInfo1.setId(id+12);
    userInfo1.setName("李四");
    userInfo1.setAge("39");

    UserInfo userInfo2=new UserInfo();
    userInfo2.setId(id+13);
    userInfo2.setName("旺旺");
    userInfo2.setAge("20");

    UserInfo userInfo3=new UserInfo();
    userInfo3.setId(id+14);
    userInfo3.setName("王伟");
    userInfo3.setAge("59");

    List<UserInfo> list=new ArrayList<>();
    list.add(userInfo);
    list.add(userInfo1);
    list.add(userInfo2);
    list.add(userInfo3);

    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    userInfoDao.insertInTx(list);
}

 

大于 gt

/**
 * 查询数据列表 年龄大于30
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.gt("30")).list();
    return list;
}

 

 

大于等于 ge

/**
 * 查询数据列表 年龄大于等于30
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.ge("30")).list();
    return list;
}

 

 

小于 lt

/**
 * 查询数据列表 年龄小于30
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.lt("30")).list();
    return list;
}

 

 

 

小于等于 le

/**
 * 查询数据列表 年龄小于等于30
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.le("30")).list();
    return list;
 }

 

 

 

两者之间 between (包含 开头和结尾)

/**
 * 查询数据列表 年龄【30,59】
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.between("30","59")).list();
    return list;
}

 

 

 

 

<4> 升序降序

插入的数据和(3)一样

 

升序

/**
 * 查询数据列表 按年龄升序排序
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.orderAsc(UserInfoDao.Properties.Age).list();
    return list;
}

 

 

 

降序

/**
 * 查询数据列表 按年龄降序排序
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.orderDesc(UserInfoDao.Properties.Age).list();
    return list;
}

 

 

组合

/**
 * 查询数据列表 年龄【30,59】然后再降序排序
 */

public List<UserInfo> queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    List<UserInfo> list = qb.where(UserInfoDao.Properties.Age.between("30","59")).orderDesc(UserInfoDao.Properties.Age).list();
    return list;
}

 

 

 

 

 

四.缓存问题

 

如果GreenDao开启了缓存,所以当你调用 某一条查询语句 取得 A实体,然后对 A实体 进行修改并更新到数据库,接着再调用 某一条查询语句 取得 A实体,会发现X实体的内容依旧是修改前的。其实你的修改已经更新到数据库中,只是查询采用了缓存,所以直接返回了第一次查询的实体。

 

//清空所有数据表的缓存数据
DaoSession daoSession =MyApplication.getDaoInstant();
daoSession .clear();

//清空某个数据表的缓存数据
UserInfoDao movieCollectDao = MyApplication.getDaoInstant().getUserInfoDao();
movieCollectDao.detachAll();

 

本人代码 没有设置缓存

 

/**
 * 各种点击事件的方法
 */

@Override
public void onClick(View v) {
    switch (v.getId()) {
        case R.id.activity_greendaocache_textview1://1.查
            userInfo=queryUserList();
            String result="ID:"+userInfo.getId()+"  姓名:"+userInfo.getName()+"  "+"年龄:"+userInfo.getAge();
            textView.setText(result);
            break;
        case R.id.activity_greendaocache_textview2://2.改
           if(null!=userInfo){
               //修改
                userInfo.setAge("1111");
                userInfo.setName("张三");
                //将修改的内容更新到数据库
                UserInfoDao userInfoDao=MyApplication.getDaoInstant().getUserInfoDao();
                userInfoDao.update(userInfo);
            }
            break;
        case R.id.activity_greendaocache_textview3://3.查
            UserInfo userInfo=queryUserList();
            String results="ID(新):"+userInfo.getId()+"  姓名(新):"+userInfo.getName()+"  "+"年龄(新):"+userInfo.getAge();
            textView.setText(results);
            break;
        case R.id.activity_greendaocache_textview11://1.查(清缓存)

            break;
        case R.id.activity_greendaocache_textview22://2.改(清缓存)

            break;
        case R.id.activity_greendaocache_textview33://3.查(清缓存)

            break;
        default:
            break;
    }
}

/**
 * 查询一条数据列表 姓名=“张三”
 */

public UserInfo queryUserList() {
    UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
    QueryBuilder<UserInfo> qb = userInfoDao.queryBuilder();
    UserInfo userInfo = qb.where(UserInfoDao.Properties.Name.eq("张三")).unique();
    return userInfo;
}

 

 

 

 

 

 

 

 

 

五.加密

 

1.默认获取

private void setupDatabase() {
    //创建数据库shop.db 创建SQLite数据库的SQLiteOpenHelper的具体实现
    DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "greendaodemo.db", null);
    //获取SQLiteDatabase对象
    SQLiteDatabase db = helper.getReadableDatabase();
    //获取数据库对象
    DaoMaster daoMaster = new DaoMaster(db);
    //获取dao对象管理者
    daoSession = daoMaster.newSession();
}

 

获取 SQLiteDatabase 对象

//获取SQLiteDatabase对象
SQLiteDatabase db = helper.getReadableDatabase();

 

获取 DaoMaster 对象

//获取数据库对象
DaoMaster daoMaster = new DaoMaster(db);

 

此时 DaoMaster 构造方法

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

 

 

 

2.加密获取

 

添加配置

implementation 'net.zetetic:android-database-sqlcipher:3.5.7'

 

获取

private void setupDatabase() {
   //创建数据库shop.db 创建SQLite数据库的SQLiteOpenHelper的具体实现
    DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "greendaodemo.db", null);
    //获取Database对象
    Database db = helper.getEncryptedReadableDb("1q2w3e4r");
    //获取数据库对象
     DaoMaster daoMaster = new DaoMaster(db);
    //获取dao对象管理者
    daoSession = daoMaster.newSession();
}

 

 

获取 Database 对象

 //获取Database对象
Database db = helper.getEncryptedReadableDb("1q2w3e4r");

 

 

获取 DaoMaster 对象

 //获取数据库对象
 DaoMaster daoMaster = new DaoMaster(db);

 

 

此时DaoMaster构造方法

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

 

 

获取 Database 对象 其他方法

 

 

 

3.说明

加密需要添加sqlcipher库,而该库体积庞大,使用后apk大小会增加大概10M,所以如果你的应用对安全性要求不高,不建议使用。

 

 

加密前APK大小

 

 

加密后APK大小

 

 

代码链接:https://github.com/wujianning/AndroidDBDemo

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值