greendao 的使用
参考文章一篇技术好文之Android数据库 GreenDao的使用完全解析
在Android 中的数据库操作,除了Android 原生的SqliteOpenHelper 之外,还有许多优秀的三方框架可以使用,比如GreenDao, OrmLite,ActiveAndroid,以及Litepal,都是比较不错的.无论是从性能上还是,使用难度上,都是比较友好的!其中GreenDao尤其出众,使用者众多,好评一片.之前一直用的都是Litepal,专门学习一下,特此记录
greendao 中核心操作数据库的类说明
-
DaoMaster
DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。它有静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper是SQLiteOpenHelper实现,它们在SQLite数据库中创建模式。
-
DaoSession
管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取该对象。DaoSession还提供了一些通用的持久性方法,如实体的插入,加载,更新,刷新和删除。
-
XXXDao
数据访问对象(DAO)持久存在并查询实体。对于每个实体,greenDAO生成DAO。它具有比DaoSession更多的持久性方法,例如:count,loadAll和insertInTx。
这几个类都会自动生成在build.gradle内指定的目录下
集成
在project 的build.gradle中添加以下内容:
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
然后在moudle 的build.gradle中添加如下内容:
apply plugin: 'org.greenrobot.greendao' // apply plugin
android{
...
greendao{
schemaVersion 1 //数据库的版本
daoPackage 'com.sunkaisens.ffmpegtest.greendao'//greendao 自动生成的辅助类
targetGenDir 'src/main/java'//固定目录
}
}
...
dependencies {
implementation 'org.greenrobot:greendao:3.2.2' // add library
}
至此,集成完毕
还需要在Application 中进行初始化操作,
内容如下:
public class MyApp extends Application {
private static final String DATANAME_NAME = "sunkaisens.db";//数据库名称
private static DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
initDaoSession();
}
private void initDaoSession() {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, DATANAME_NAME);
SQLiteDatabase database = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(database);
daoSession = daoMaster.newSession();
}
public static DaoSession getSession() {
return daoSession;
}
}
记得在manifests文件中声名.name属性
操作数据库
先说明以下greendao 对象映射的一些注解说明,参考GreenDao3 api、注解说明
-
@Entity
指定一个数据库实体
public @interface Entity {
/**
* 在数据库中表的名称,默认为实体的类名
*/
String nameInDb() default "";
/**
* 定义索引,可以跨越多个列(默认为实体类成员变量的个数)
*/
Index[] indexes() default {};
/**
* 标记创建数据库表
* 若一个表映射多个实体类或者创建表外应的GreenDao,设置为false
*/
boolean createInDb() default true;
/**
* 告知GreenDao当前实体属于哪个schema
*/
String schema() default "default";
/**
* 实体活动状体标志位(默认为false)
* 若设置为true,实体有更新、删除和刷新方法
*/
boolean active() default false;
}
-
@Convert:
这个类十分有用,可以将数据库中字段类型与entity中的类型进行你需要的转换
public @interface Convert {
/** 转换类*/
Class<? extends PropertyConverter> converter();
/**
* 在数据库中持久化的列
* 此受限于GreenDao所支持的类
*/
Class columnType();
}
-
@Id
设置主键 Long型,可以通过@Id(autoincrement = true)设置自增长。通过这个注解标记的字段必须是Long,数据库中表示它就是主键,并且默认是自增的。
public @interface Id {
/**
* 设置是否为自增长,默认为false
*/
boolean autoincrement() default false;
}
- @Index
使用@Index作为一个属性来创建一个索引;定义多列索引(@link Entity#indexes())
public @interface Index {
/**
* 通过逗号间隔创建表的属性索引,例如 “propertyA,propertyB,propertyC”
* 若要指定排序, 需在列明以后添加 ASC(升序) 或者DESC(降序) , 例如 "propertyA DESC, propertyB ASC"
* 只有实体类中使用 {@link Entity#indexes()} 才可设置
*/
String value() default "";
/**
* 表的可选索引
* 默认为实体类中的成员变量
*/
String name() default "";
/**
* 是否为属性设置唯一属性,默认为false
*/
boolean unique() default false;
}
- @JoinEntity
定义表连接关系
public @interface JoinEntity {
/** 添加的实体类 */
Class<?> entity();
/** 源表的列索引 */
String sourceProperty();
/** 连接表内拥有源实体的属性*/
String targetProperty();
}
- @JoinProperty
定义名称和引用名称属性关系
public @interface JoinProperty {
/** 实体中的名称,对应于引用的名称 */
String name();
/** 引用的名称 */
String referencedName();
}
- @OrderBy
排序
public @interface OrderBy {
/**
* 通过逗号间隔创建表的属性索引,例如 “propertyA,propertyB,propertyC”
* 若要指定排序, 需在列明以后添加 ASC(升序) 或者DESC(降序) , 例如 "propertyA DESC, propertyB ASC"
* 默认按升序排序
* 若不设置默认根据主键排序
*/
String value() default "";
}
- @Property
指定数据库数据字段名
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.FIELD)
public @interface Property {
/**
* Name of the database column for this property. Default is field name.
*/
String nameInDb() default "";
}
- @Unique
向数据库列添加了一个唯一的约束
- @Transient
表明这个字段不会被写入数据库,只是作为一个属性存在
函数说明:
void attachEntity(T entity):
long count():获取数据库中数据的数量
// 数据删除相关
void delete(T entity):从数据库中删除给定的实体
void deleteAll() :删除数据库中全部数据
void deleteByKey(K key):从数据库中删除给定Key所对应的实体
void deleteByKeyInTx(java.lang.Iterable<K> keys):使用事务操作删除数据库中给定的所有key所对应的实体
void deleteByKeyInTx(K... keys):使用事务操作删除数据库中给定的所有key所对应的实体
void deleteInTx(java.lang.Iterable<T> entities):使用事务操作删除数据库中给定实体集合中的实体
void deleteInTx(T... entities):使用事务操作删除数据库中给定的实体
// 数据插入相关
long insert(T entity):将给定的实体插入数据库
void insertInTx(java.lang.Iterable<T> entities):使用事务操作,将给定的实体集合插入数据库
void insertInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey):使用事务操作,将给定的实体集合插入数据库,
并设置是否设定主键
void insertInTx(T... entities):将给定的实体插入数据库
long insertOrReplace(T entity):将给定的实体插入数据库,若此实体类存在,则覆盖
void insertOrReplaceInTx(java.lang.Iterable<T> entities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖
void insertOrReplaceInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖
并设置是否设定主键
void insertOrReplaceInTx(T... entities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则覆盖
long insertWithoutSettingPk(T entity):将给定的实体插入数据库,但不设定主键
// 新增数据插入相关API
void save(T entity):将给定的实体插入数据库,若此实体类存在,则更新
void saveInTx(java.lang.Iterable<T> entities):将给定的实体插入数据库,若此实体类存在,则更新
void saveInTx(T... entities):使用事务操作,将给定的实体插入数据库,若此实体类存在,则更新
// 加载相关
T load(K key):加载给定主键的实体
java.util.List<T> loadAll():加载数据库中所有的实体
protected java.util.List<T> loadAllAndCloseCursor(android.database.Cursor cursor) :从cursor中读取、返回实体的列表,并关闭该cursor
protected java.util.List<T> loadAllFromCursor(android.database.Cursor cursor):从cursor中读取、返回实体的列表
T loadByRowId(long rowId) :加载某一行并返回该行的实体
protected T loadUnique(android.database.Cursor cursor) :从cursor中读取、返回唯一实体
protected T loadUniqueAndCloseCursor(android.database.Cursor cursor) :从cursor中读取、返回唯一实体,并关闭该cursor
//更新数据
void update(T entity) :更新给定的实体
protected void updateInsideSynchronized(T entity, DatabaseStatement stmt, boolean lock)
protected void updateInsideSynchronized(T entity, android.database.sqlite.SQLiteStatement stmt, boolean lock)
void updateInTx(java.lang.Iterable<T> entities) :使用事务操作,更新给定的实体
void updateInTx(T... entities):使用事务操作,更新给定的实体
举例:
@Entity()
public class User {
@Id(autoincrement = true)
private Long id;
@NotNull //不能为空
@Unique //唯一
@Property(nameInDb = "username")
private String name;
@NotNull
@Unique
@Property(nameInDb = "userage")
private int age;
@Transient //表明这个字段不会被写入数据库,只是作为一个属性存在
private String like;
@Generated(hash = 955858333)
public User(Long id, @NotNull String name, int age) {
this.id = id;
this.name = name;
this.age = age;
}
@Generated(hash = 586692638)
public User() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return this.age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString() {
return "User{" +
"id=" + id +
", name='" + name + '\'' +
", age=" + age +
", like='" + like + '\'' +
'}';
}
}
...
//插入数据
User user = new User(null, "张三", 23);
long insert =MyApp.getSession().getUserDao().insertOrReplace(user);
//删除数据
MyApp.getSession().getUserDao().delete(user);
MyApp.getSession().getUserDao().deleteAll();
如果需要按条件删除,可以先按条件查询:
//查询 age >= 26 的 user
List<User> userList = userDao.queryBuilder().where(UserDao.Properties.Age.ge(26)).list();
然后遍历集合删除即可
修改 同理,先查出数据然后修改数据,在更新
//取出符合条件的唯一数据,必须保证比对的条件在数据库内是唯一的,不然会报错
User unique = userDao.queryBuilder().where(UserDao.Properties.Name.eq("value")).unique();
unique.setAge(44);
userDao.update(unique);
QueryBuilder的使用
QueryBuilder的常见方法:
- where(WhereCondition cond, WhereCondition... condMore): 查询条件,参数为查询的条件!
- or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件或者,用法同or。
- and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore): 嵌套条件且,用法同and。
- join(Property sourceProperty, Class<J> destinationEntityClass):多表查询,后面会讲。
输出结果有四种方式,选择其中一种最适合的即可,list()返回值是List,而其他三种返回值均实现Closeable,需要注意的不使用数据时游标的关闭操作: - list ()所有实体都加载到内存中。结果通常是一个没有魔法的 ArrayList。最容易使用。
- listLazy ()实体按需加载到内存中。首次访问列表中的元素后,将加载并缓存该元素以供将来使用。必须关闭。
- listLazyUncached ()实体的“虚拟”列表:对列表元素的任何访问都会导致从数据库加载其数据。必须关闭。
- listIterator ()让我们通过按需加载数据(懒惰)来迭代结果。数据未缓存。必须关闭。
- orderAsc() 按某个属性升序排;
- orderDesc() 按某个属性降序排;
GreenDao中SQL语句的缩写,我们也了解下,源码在Property中,使用的时候可以自己点进去查询即可:
- eq():"equal ('=?')" 等于;
- notEq() :"not equal ('<>?')" 不等于;
- like():" LIKE ?" 值等于;
- between():" BETWEEN ? AND ?" 取中间范围;
- in():" IN (" in命令;
- notIn():" NOT IN (" not in 命令;
- gt():">?" 大于;
- lt():"<? " 小于;
- ge():">=?" 大于等于;
- le():"<=? " 小于等于;
- isNull():" IS NULL" 为空;
- isNotNull():" IS NOT NULL" 不为空;
网友评论