上一节讲述了GreenDao数据库的基础讲解:Android GreenDao数据库—基础详解
本章节讲述GreenDao数据库的高级讲解
public class UserInfoDao extends AbstractDao {
public static final String TABLENAME = "USER_INFO";
/**
* Properties of entity UserInfo.
* 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.增
1.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);
}
1.2.插入多条数据
/**
* 插入多条记录
*/
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 list=new ArrayList<>();
list.add(userInfo1);
list.add(userInfo2);
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//插入多条数据
userInfoDao.insertInTx(list);
}
2.插入或替换(插入的数据如果已经存在表中,则替换掉旧数据(根据主键来检测是否已经存在))
2.1.插入或替换一条数据
/**
* 插入或替换一条记录
*/
public void insertUser() {
//获取实体类
UserInfo userInfo=new UserInfo();
userInfo.setId(id);
userInfo.setName("张三");
userInfo.setAge("29");
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//插入或替换一条数据
userInfoDao.insertOrReplace(userInfo);
}
2.2.插入或替换多条数据
/**
* 插入或替换多条记录
*/
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 list=new ArrayList<>();
list.add(userInfo1);
list.add(userInfo2);
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//插入或替换多条数据
userInfoDao.insertOrReplaceInTx(list);
}
3.删
3.1.删除一条数据
/**
* 删除一条记录
*/
public void deleteUser() {
//获取实体类
UserInfo userInfo=new UserInfo();
userInfo.setId(id);
userInfo.setName("张三");
userInfo.setAge("29");
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//删除一条数据
userInfoDao.delete(userInfo);
}
3.2.删除多条数据
/**
* 删除多条记录
*/
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 list=new ArrayList<>();
list.add(userInfo1);
list.add(userInfo2);
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//删除多条数据
userInfoDao.deleteInTx(list);
}
3.3.删除全部数据
/**
* 删除所有记录
*/
public void deleteUser() {
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//删除所有数据
userInfoDao.deleteAll();
}
4.改
4.1.修改一条数据
/**
* 更新一条记录
*/
public void updateUser() {
//获取实体类
UserInfo userInfo=new UserInfo();
userInfo.setId(id);
userInfo.setName("张三更新");
userInfo.setAge("30");
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//更新一条数据
userInfoDao.update(userInfo);
}
4.2.修改多条数据
/**
* 更新多条记录
*/
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 list=new ArrayList<>();
list.add(userInfo1);
list.add(userInfo2);
//获取相应的Dao
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
//更新多条数据
userInfoDao.updateInTx(list);
}
5.查
5.1.查询全部数据
5.1.1.QueryBuilder 查询全部
/**
* 查询数据列表
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.list();
return list;
}
5.1.2.loadAll 查询全部
/**
* 查询数据列表
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
List list = userInfoDao.loadAll();
return list;
}
5.2.查询数量
/**
* 查询数据列表数量
*/
public long queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
long count=userInfoDao.count();
return count;
}
5.3.条件查询
5.3.1.精确查询(where)
/**
* 查询多条数据 姓名=“张三”
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Name.eq("张三")).list();
return list;
}
/**
* 查询一条数据 姓名=“张三”
*/
public UserInfo queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
UserInfo userInfo = qb.where(UserInfoDao.Properties.Name.eq("张三")).unique();
return userInfo;
}
5.3.2.模糊查询(like)
/**
* 查询数据列表 姓名以“张” 开头
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Name.like("张%")).list();
return list;
}
/**
* 查询数据列表 姓名以“三” 结尾
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Name.like("%三")).list();
return list;
}
5.3.3.区间查询
插入的数据
/**
* 插入多条记录
*/
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 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 queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Age.gt("30")).list();
return list;
}
大于等于 ge
/**
* 查询数据列表 年龄大于等于30
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Age.ge("30")).list();
return list;
}
小于 lt
/**
* 查询数据列表 年龄小于30
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Age.lt("30")).list();
return list;
}
小于等于 le
/**
* 查询数据列表 年龄小于等于30
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Age.le("30")).list();
return list;
}
两者之间 between (包含 开头和结尾)
/**
* 查询数据列表 年龄【30,59】
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.where(UserInfoDao.Properties.Age.between("30","59")).list();
return list;
}
5.4.升序降序
插入的数据和5.3.3一样
升序
/**
* 查询数据列表 按年龄升序排序
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.orderAsc(UserInfoDao.Properties.Age).list();
return list;
}
降序
/**
* 查询数据列表 按年龄降序排序
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List list = qb.orderDesc(UserInfoDao.Properties.Age).list();
return list;
}
组合
/**
* 查询数据列表 年龄【30,59】然后再降序排序
*/
public List queryUserList() {
UserInfoDao userInfoDao= MyApplication.getDaoInstant().getUserInfoDao();
QueryBuilder qb = userInfoDao.queryBuilder();
List 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 qb = userInfoDao.queryBuilder();
UserInfo userInfo = qb.where(UserInfoDao.Properties.Name.eq("张三")).unique();
return userInfo;
}
1.查
3.查
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();
}
1.1.获取 SQLiteDatabase 对象
//获取SQLiteDatabase对象
SQLiteDatabase db = helper.getReadableDatabase();
1.2.获取 DaoMaster 对象
//获取数据库对象
DaoMaster daoMaster = new DaoMaster(db);
1.3.此时 DaoMaster 构造方法
public DaoMaster(SQLiteDatabase db) {
this(new StandardDatabase(db));
}
2.加密获取
2.1.添加配置
implementation 'net.zetetic:android-database-sqlcipher:3.5.7'
2.2.获取
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();
}
2.3.获取 Database 对象
//获取Database对象
Database db = helper.getEncryptedReadableDb("1q2w3e4r");
2.4.获取 DaoMaster 对象
//获取数据库对象
DaoMaster daoMaster = new DaoMaster(db);
2.5.此时DaoMaster构造方法
public DaoMaster(Database db) {
super(db, SCHEMA_VERSION);
registerDaoClass(PeopleDao.class);
registerDaoClass(UserInfoDao.class);
}
2.6.获取 Database 对象 其他方法
3.说明
加密需要添加sqlcipher库,而该库体积庞大,使用后apk大小会增加大概10M,所以如果你的应用对安全性要求不高,不建议使用。
加密前APK大小
加密后APK大小
代码链接:https://github.com/wujianning/AndroidDBDemo