GreenDao3 使用说明

来源:互联网 发布:淘宝sony耳机真假 编辑:程序博客网 时间:2024/06/16 13:29
Logo写文章注册登录

GreenDao3 使用说明

96 
作者 离羊 关注
2016.11.09 23:34* 字数 623 阅读 8826评论 16

GreenDao 3

一个将对象映射到 SQLite 数据库中的轻量且快速的ORM解决方案

资料

Github

官网

android-database-sqlcipher Github
数据库加密

GreenDaoUpgradeHelper Github
数据库升级辅助

导入

  • 配置项目的 build.gradle
buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'    }}// 使用数据库升级辅助GreenDaoUpgradeHelper时添加allprojects {        repositories {                ...                maven { url "https://jitpack.io" }        }}
  • 配置模组的 build.gradle
apply plugin: 'org.greenrobot.greendao'dependencies {        compile 'org.greenrobot:greendao:3.2.0'        // 数据库加密时添加        compile 'net.zetetic:android-database-sqlcipher:3.5.1'        // 使用数据库升级辅助GreenDaoUpgradeHelper时添加        compile 'com.github.yuweiguocn:GreenDaoUpgradeHelper:v1.2.0'}
  • 设置 Schema,在模组的 build.gradle 中添加:
    • schemaVersion:数据库schema版本号,通过*OpenHelpers迁移数据,schema改变值增加。默认为1
    • daoPackage:生成DAOs、DaoMaster、DaoSession的包名。默认为entities所在包名。
    • targetGenDir:生成DAOs、DaoMaster、DaoSession的目录。默认为build/generated/source/greendao
    • generateTests: 设置true自动生成单元测试。
    • targetGenDirTests: 设置生成单元测试目录。默认为src/androidTest/java
greendao {    schemaVersion 1    daoPackage 'com.example.greendaodemo.dao'    targetGenDir 'src/main/java'}

混淆

  • 配置模组的 proguard-rules.pro
### greenDAO 3-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {public static java.lang.String TABLENAME;}-keep class **$Properties# If you do not use SQLCipher:-dontwarn org.greenrobot.greendao.database.**# If you do not use RxJava:-dontwarn rx.**

基本用法

实体

@Entity(        // schema 名,多个 schema 时设置关联实体。插件产生不支持,需使用产生器        // schema = "myschema",        // 标记一个实体是否处于活动状态,活动实体有 update、delete、refresh 方法。默认为 false        active = false,        // 表名,默认为类名        nameInDb = "AWESOME_USERS",        // 定义多列索引        indexes = {                @Index(value = "name DESC", unique = true)        },        // 标记是否创建表,默认 true。多实体对应一个表或者表已创建,不需要 greenDAO 创建时设置 false        createInDb = true,        // 是否产生所有参数构造器。默认为 true。无参构造器必定产生        generateConstructors = true,        // 如果没有 get/set 方法,是否生成。默认为 true        generateGettersSetters = true)public class User {    // 主键,autoincrement设置自增    @Id(autoincrement = true)    private Long id;    // 唯一,默认索引    @Unique    private Long userId;    // 列名,默认使用变量名。变化:customName --> CUSTOM_NAME    @Property(nameInDb = "USERNAME")    private String name;    // 索引,unique设置唯一,name设置索引别名    @Index(unique = true)    private long fk_dogId;    // 非空    @NotNull    private String horseName;    // 忽略,不持久化,可用关键字transient替代    @Transient    private int tempUsageCount;    // 对一,实体属性 joinProperty 对应外联实体ID    @ToOne(joinProperty = "fk_dogId")    private Dog dog;    // 对多。实体ID对应外联实体属性 referencedJoinProperty    @ToMany(referencedJoinProperty = "fk_userId")    private List<Cat> cats;    // 对多。@JoinProperty:name 实体属性对应外联实体属性 referencedName    @ToMany(joinProperties = {            @JoinProperty(name = "horseName", referencedName = "name")    })    private List<Horse> horses;    // 对多。@JoinEntity:entity 中间表;中间表属性 sourceProperty 对应实体ID;中间表属性 targetProperty 对应外联实体ID    @ToMany    @JoinEntity(            entity = JoinUserWithSheep.class,            sourceProperty = "uId",            targetProperty = "sId"    )    private List<Sheep> sheep;}
  • @Generated:greenDao生产代码注解,手动修改报错
  • @Keep:替换@Generated,greenDao不再生成,也不报错。@Generated(无hash)也有相同的效果
  • @ToOne:joinProperty 和对象联动,同时改变。对象懒加载,第一次请求后缓存
  • @ToMany:集合懒加载并缓存,之后获取集合不查找数据库,即集合数据不变。须手动修改集合,或调用reset方法清理集合

关系

  • User 和 Cat 配合产生一对多关系
@Entitypublic class Cat {    @Id    private Long id;    private String name;    private long fk_userId;    @ToOne(joinProperty = "fk_userId")    private User user;}
  • User、Sheep 和中间类 JoinUserWithSheep 配合产生多对多关系
@Entitypublic class Sheep {    @Id    private Long id;    private String name;    @ToMany    @JoinEntity(            entity = JoinUserWithSheep.class,            sourceProperty = "sId",            targetProperty = "uId"    )    private List<User> users;}@Entitypublic class JoinUserWithSheep {    @Id    private Long id;    private Long uId;    private Long sId;}
  • 多个 TreeNode 配合产生树状关系
@Entitypublic class TreeNode {    @Id    private Long id;    private Long parentId;    @ToOne(joinProperty = "parentId")    private TreeNode parent;    @ToMany(referencedJoinProperty = "parentId")    private List<TreeNode> children;}

初始化

// Application 中执行// DevOpenHelper 每次数据库升级会清空数据,一般用于开发DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);Database db = helper.getWritableDb();DaoSession daoSession = new DaoMaster(db).newSession();// 在使用的地方获取 DAONoteDao noteDao = daoSession.getNoteDao();

Dao 增加

long     insert(T entity)  // 插入指定实体void     insertInTx(T... entities)void     insertInTx(java.lang.Iterable<T> entities)void     insertInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey)long     insertWithoutSettingPk(T entity)  // 插入指定实体,无主键long     insertOrReplace(T entity)  // 插入或替换指定实体void     insertOrReplaceInTx(T... entities)void     insertOrReplaceInTx(java.lang.Iterable<T> entities)void     insertOrReplaceInTx(java.lang.Iterable<T> entities, boolean setPrimaryKey)void     save(T entity)  // 依赖指定的主键插入或修改实体void     saveInTx(T... entities)void     saveInTx(java.lang.Iterable<T> entities)

Dao 删除

void     deleteAll()  // 删除所有void     delete(T entity)  // 删除指定的实体void     deleteInTx(T... entities)void     deleteInTx(java.lang.Iterable<T> entities)void     deleteByKey(K key)  // 删除指定主键对应的实体void     deleteByKeyInTx(K... keys)void     deleteByKeyInTx(java.lang.Iterable<K> keys)

Dao 修改

void     update(T entity)void     updateInTx(T... entities)void     updateInTx(java.lang.Iterable<T> entities)

Dao 其它

void     refresh(T entity)  // 从数据库获取值刷新本地实体long     count()  // 数量boolean     detach(T entity)  // 从域中分离实体void     detachAll()  // 从域中分离所有实体AbstractDaoSession     getSession()Database     getDatabase()java.lang.String     getTablename()java.lang.String[]     getAllColumns()java.lang.String[]     getPkColumns()java.lang.String[]     getNonPkColumns()Property     getPkProperty()Property[]     getProperties()

Dao 查询

java.util.List<T>     loadAll()T     load(K key)T     loadByRowId(long rowId)

QueryBuilder 查询

List joes = userDao.queryBuilder()  // 查询 User                .where(Properties.FirstName.eq("Joe"))  // 首名为 Joe                .orderAsc(Properties.LastName)  // 末名升序排列                .list();  // 返回集合// Joe,>= 1970.10QueryBuilder qb = userDao.queryBuilder();qb.where(Properties.FirstName.eq("Joe"),                qb.or(Properties.YearOfBirth.gt(1970),                                qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));List youngJoes = qb.list();
QueryBuilder<T>     queryBuilder()  // Dao// QueryBuilderQueryBuilder<T>     where(WhereCondition cond, WhereCondition... condMore)  // 条件,AND 连接QueryBuilder<T>     whereOr(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore)  // 条件,OR 连接QueryBuilder<T>     distinct()  // 去重,例如使用联合查询时QueryBuilder<T>     limit(int limit)  // 限制返回数QueryBuilder<T>     offset(int offset)  // 偏移结果起始位,配合limit(int)使用QueryBuilder<T>     orderAsc(Property... properties)  // 排序,升序QueryBuilder<T>     orderDesc(Property... properties)  // 排序,降序QueryBuilder<T>     orderCustom(Property property, java.lang.String customOrderForProperty)  // 排序,自定义QueryBuilder<T>     orderRaw(java.lang.String rawOrder)  // 排序,SQL 语句QueryBuilder<T>     preferLocalizedStringOrder()  // 本地化字符串排序,用于加密数据库无效QueryBuilder<T>     stringOrderCollation(java.lang.String stringOrderCollation)  // 自定义字符串排序,默认不区分大小写WhereCondition     and(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore)  // 条件,AND 连接WhereCondition     or(WhereCondition cond1, WhereCondition cond2, WhereCondition... condMore)  // 条件,OR 连接

Query 重复查询

// Joe,1970Query query = userDao.queryBuilder().where(    Properties.FirstName.eq("Joe"), Properties.YearOfBirth.eq(1970)).build();List joesOf1970 = query.list();// Maria,1977query.setParameter(0, "Maria");query.setParameter(1, 1977);List mariasOf1977 = query.list();
// QueryBuilderQuery<T>     build()CursorQuery     buildCursor()CountQuery<T>     buildCount()DeleteQuery<T>     buildDelete()// Query// 设置查询参数,从 0 开始Query<T>     setParameter(int index, java.lang.Object parameter)Query<T>     setParameter(int index, java.lang.Boolean parameter)Query<T>     setParameter(int index, java.util.Date parameter)void     setLimit(int limit)  // 限制返回数void     setOffset(int offset)  // 偏移结果起始位,配合limit(int)使用// Query 绑定线程,执行非本线程的 Query 抛异常,调用获取本线程 QueryQuery<T>     forCurrentThread()  // 获取本线程 Query

获取查询结果

// QueryBuilder、QueryT     unique()  // 返回唯一结果或者 nullT     uniqueOrThrow()  // 返回唯一非空结果,如果 null 则抛异常java.util.List<T>     list()  // 返回结果集进内存// 懒加载,须在 try/finally 代码中关闭。LazyList<T>     listLazy()  // 第一次使用返回结果集,所有数据使用后会自动关闭LazyList<T>     listLazyUncached()  // 返回虚拟结果集,数据库读取不缓存CloseableListIterator<T>     listIterator()  // 懒加载数据迭代器,不缓存,所有数据使用后会自动关闭// QueryBuilder、CountQuerylong     count()  // 获取结果数量

SQL 查询

// QueryBuilder.where() 配合 WhereCondition.StringCondition() 实现SQL查询Query query = userDao.queryBuilder()                .where(new WhereCondition.StringCondition("_ID IN (SELECT USER_ID FROM USER_MESSAGE WHERE READ_FLAG = 0)"))                .build();// Dao.queryRawCreate() 实现SQL查询Query query = userDao.queryRawCreate(  ", GROUP G WHERE G.NAME=? AND T.GROUP_ID=G._ID", "admin");
// Daojava.util.List<T>     queryRaw(java.lang.String where, java.lang.String... selectionArg)Query<T>     queryRawCreate(java.lang.String where, java.lang.Object... selectionArg)Query<T>     queryRawCreateListArgs(java.lang.String where, java.util.Collection<java.lang.Object> selectionArg)// WhereCondition.PropertyConditionPropertyCondition(Property property, java.lang.String op)PropertyCondition(Property property, java.lang.String op, java.lang.Object value)PropertyCondition(Property property, java.lang.String op, java.lang.Object[] values)// WhereCondition.StringConditionStringCondition(java.lang.String string)StringCondition(java.lang.String string, java.lang.Object value)StringCondition(java.lang.String string, java.lang.Object... values)

DeleteQuery 删除查询

DeleteQuery<T>     buildDelete()  // QueryBuilder

查询日志

QueryBuilder.LOG_SQL = true;QueryBuilder.LOG_VALUES = true;

DaoSession 增删改查

// DaoSession 的方法转换成 Dao 的对应方法执行<T> long     insert(T entity)<T> long     insertOrReplace(T entity)<T> void     delete(T entity)<T> void     deleteAll(java.lang.Class<T> entityClass)<T> void     update(T entity)<T,K> T     load(java.lang.Class<T> entityClass, K key)<T,K> java.util.List<T>     loadAll(java.lang.Class<T> entityClass)<T> QueryBuilder<T>     queryBuilder(java.lang.Class<T> entityClass)<T,K> java.util.List<T>     queryRaw(java.lang.Class<T> entityClass, java.lang.String where, java.lang.String... selectionArgs)<T> void     refresh(T entity)

进阶用法

联合查询

// 芝麻街住户QueryBuilder<User> queryBuilder = userDao.queryBuilder();queryBuilder.join(Address.class, AddressDao.Properties.userId)                .where(AddressDao.Properties.Street.eq("Sesame Street"));List<User> users = queryBuilder.list();// 欧洲超过百万人口的城市QueryBuilder qb = cityDao.queryBuilder().where(Properties.Population.ge(1000000));Join country = qb.join(Properties.CountryId, Country.class);Join continent = qb.join(country, CountryDao.Properties.ContinentId,                Continent.class, ContinentDao.Properties.Id);continent.where(ContinentDao.Properties.Name.eq("Europe"));List<City> bigEuropeanCities = qb.list();// 爷爷叫林肯的人QueryBuilder qb = personDao.queryBuilder();Join father = qb.join(Person.class, Properties.FatherId);Join grandfather = qb.join(father, Properties.FatherId, Person.class, Properties.Id);grandfather.where(Properties.Name.eq("Lincoln"));List<Person> lincolnDescendants = qb.list();
// QueryBuilder,联合查询<J> Join<T,J>     join(java.lang.Class<J> destinationEntityClass, Property destinationProperty)<J> Join<T,J>     join(Property sourceProperty, java.lang.Class<J> destinationEntityClass)<J> Join<T,J>     join(Property sourceProperty, java.lang.Class<J> destinationEntityClass, Property destinationProperty)<J> Join<T,J>     join(Join<?,T> sourceJoin, Property sourceProperty, java.lang.Class<J> destinationEntityClass, Property destinationProperty)

自定义类型

默认支持类型:byte[]StringDate
booleanintshortlongfloatdoublebyte
BooleanIntegerShortLongFloatDoubleByte

// enum 转换为 Integer@Entitypublic class User {    @Id    private Long id;    @Convert(converter = RoleConverter.class, columnType = Integer.class)    private Role role;    public enum Role {        DEFAULT(0), AUTHOR(1), ADMIN(2);        final int id; // 使用稳定的 id 来转换,不要使用不稳定的名字和顺序        Role(int id) {            this.id = id;        }    }    public static class RoleConverter implements PropertyConverter<Role, Integer> {        @Override        public Role convertToEntityProperty(Integer databaseValue) {            if (databaseValue == null) {                return null;            }            for (Role role : Role.values()) {                if (role.id == databaseValue) {                    return role;                }            }            return Role.DEFAULT; // 准备一个默认值,防止数据移除时崩溃        }        @Override        public Integer convertToDatabaseValue(Role entityProperty) {            // 判断返回 null            return entityProperty == null ? null : entityProperty.id;        }    }}

升级

使用 DevOpenHelper 每次升级数据库,表会删除重建,推荐开发使用。实际使用中建立类继承 DaoMaster.OpenHelper,实现 onUpgrade()

public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {        super(context, name, factory);    }    @Override    public void onUpgrade(Database db, int oldVersion, int newVersion) {        if (oldVersion == newVersion) {            Log.d("onUpgrade", "数据库是最新版本" + oldVersion + ",不需要升级");            return;        }        Log.d("onUpgrade", "数据库从版本" + oldVersion + "升级到版本" + newVersion);        switch (oldVersion) {            case 1:                String sql = "";                db.execSQL(sql);            case 2:            default:                break;        }    }}// 初始化使用 MySQLiteOpenHelperMySQLiteOpenHelper helper = new MySQLiteOpenHelper(this, "notes-db", null);Database db = helper.getWritableDb();DaoSession daoSession = new DaoMaster(db).newSession();

另有升级辅助库 GreenDaoUpgradeHelper,通过 MigrationHelper 在删表重建的过程中,使用临时表保存数据并还原。

注意:MigrationHelper.migrate(),暂时只接收 SQLiteDatabase ,不接收 Database,影响加密的使用。可修改源码支持。

public class MySQLiteOpenHelper extends DaoMaster.OpenHelper {    public MySQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {        super(context, name, factory);    }    @Override    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {        MigrationHelper.migrate(db,TestDataDao.class,TestData2Dao.class,TestData3Dao.class);    }}// 初始化MigrationHelper.DEBUG = true; //如果你想查看日志信息,请将 DEBUG 设置为 trueMySQLiteOpenHelper helper = new MySQLiteOpenHelper(this, "test.db", null);DaoMaster daoMaster = new DaoMaster(helper.getWritableDatabase());

高阶用法

SQLCipher 加密

  • 使用getEncryptedReadableDb()getEncryptedWritableDb()获取加密的数据库
  • 256位AES加密,会提升APK的大小
  • Robolectric 测试时,须使用非加密数据库
DevOpenHelper helper = new DevOpenHelper(this, "notes-db-encrypted.db");Database db = helper.getEncryptedWritableDb("<your-secret-password>");DaoSession daoSession = new DaoMaster(db).newSession();

RxJava

// DaoSessionRxTransaction     rxTx()  // 返回 IO 线程下的 ObservablesRxTransaction     rxTxPlain()  // 返回无线程调度的 Observables// DaoRxDao<T,K>     rx()RxDao<T,K>     rxPlain()// QueryBuilderRxQuery<T>     rx()RxQuery<T>     rxPlain()
 Android
被以下专题收入,发现更多相似内容
Android知识
Android...
数据库
今日看点
程序员
Android潜修者
db
展开更多 
原创粉丝点击