greenDAO是时下Android最流行的一款ORM框架,其性能高,可加密,使用简洁,做android开发,如果会使用它,工作量会大大减小。其性能与其他ORM框架之比较可以查阅其官网。
目前greenDAO版本为3.1.1,greenDAO3相较于greenDAO2发生了较大的改变:可以使用注解声明schemas和实体。有两种方式使用greenDAO3,一种是使用java库的形式(greenDAO2的使用方法),一种是基于注解的形式(greenDAO3新增的)。

方式一,java库形式

1>在 src/main 目录下新建一个与 java 同层级的java-gen目录,用于存放由 greendao生成的 Bean类、DAO类、DaoMaster、DaoSession 等类:

2> 在build.gradle(app),添加 sourceSets 与依赖:

sourceSets {        main {            java.srcDirs = ['src/main/java', 'src/main/java-gen']        }    }dependencies {    compile 'org.greenrobot:greendao:3.1.0'    // This is only needed if you want to use encrypted databases    compile 'net.zetetic:android-database-sqlcipher:3.5.1'}

3>新建java库模块:File -> New -> New Module -> Java Library


4>在java库模块build.gradledependencies中添加依赖:

dependencies {    compile 'org.greenrobot:greendao-generator:3.1.0'}

5>编写java库模块生成的类,创建实体(表):

public class Generator {    public static void  main(String[] args) throws Exception {        int version = 1;        String defaultPackage = "com.example.bean";        //创建模式对象,指定版本号和自动生成的bean对象的包名        Schema schema = new Schema(version, defaultPackage);        //指定自动生成的dao对象的包名,不指定则都DAO类生成在"com.example.bean"包中        schema.setDefaultJavaPackageDao("com.example.dao");        //添加实体        addEntity(schema);        //java-gen绝对路径        String outDir = "H:/Persion/app/src/main/java-gen";        //调用DaoGenerator().generateAll方法自动生成代码到之前创建的java-gen目录下        new DaoGenerator().generateAll(schema, outDir);    }    private static void addEntity(Schema schema) {        //添加一个实体,会自动生成实体类Persion        Entity persion = schema.addEntity("Persion");        //指定表名,如不指定,表名则为 Persion(即实体类名)        persion.setTableName("persion");        //给实体类中添加成员(即给表中添加列,并设置列的属性)        persion.addIdProperty().autoincrement();//添加Id,自增长        persion.addStringProperty("name").notNull();//添加String类型的name,不能为空        persion.addIntProperty("age");//添加Int类型的age        persion.addDoubleProperty("high");//添加Double类型的high        ...    }}

6>运行此java类,会自动在Android项目的java-gen目录下生成bean类和DAO类:


7>转到下方 操作数据库 部分

代码说明

点击阅读greenrobot

方式二,使用注解

1>在build.gradle(app)中添加插件和依赖:

buildscript {    repositories {        mavenCentral()    }    dependencies {        classpath 'org.greenrobot:greendao-gradle-plugin:3.1.0'    }}apply plugin: 'org.greenrobot.greendao'dependencies {    compile 'org.greenrobot:greendao:3.1.0'     // This is only needed if you want to use encrypted databases    compile 'net.zetetic:android-database-sqlcipher:3.5.1'    compile 'org.greenrobot:greendao-generator:3.1.0'}

2>在build.gradle(app)中插件配置:
如果不对 greenDAO进行属性配置,在下面当”Build -> Make Project”时, greendao生成的源代码路径会是: build/generated/source/greendao。对greenDAO进行相关配置,则可以指定其路径:

greendao {    schemaVersion 1     daoPackage 'com.example.greendao'     targetGenDir 'src/main/java' }

这个greendao 可以配置的属性:

schemaVersion: 数据库schema版本号,默认为1。daoPackage: greendao生成文件 DAOs,DaoMaster,DaoSession所在的包名,默认为源码实体所在的包名。targetGenDir: 上面包所在的路径目录,默认为:build/generated/source/greendao。generateTests: 设置为true可以自动生成单元测试。targetGenDirTests:生成单元测试存储在的目录, 默认为:src/androidTest/java。

3>使用注解创建Bean类:

@Entitypublic class Persion {    @Id    private Long id;    @NotNul    private String name;    private int age;}

4>Build -> Make Project:
Make Project后,greenDAO自动为Bean类生成构造方法和每个成员的get set方法,以及前面设置的com.example.greendao包及其中的文件:

5>转到下方 操作数据库 部分

类注解

@Entity:注解实体类,标识一个表,添加的属性可以查阅依赖库中Entity注解类:

public @interface Entity {    /**     * 指定数据库中表明,默认为注解的实体类的类名     */    String nameInDb() default "";    /**     * 对实体的索引     * 

* 注意: 如果创建单列索引使用 {@link Index} */ Index[] indexes() default {}; /** * 如果设置为false,表示这个实体类不在数据库中创建表。 仅仅是一个实体类。 * 注意,greendao不会在缓存中同步多个实体。 */ boolean createInDb() default true; /** * 指定schema名字。 */ String schema() default "default"; /** * 是否可以生成update/delete/refresh方法。 *如果实体被定义成{@link ToMany} 或者 {@link ToOne} 关系,这个属性是active */ boolean active() default false; /** * 构造器是否可以生成. */ boolean generateConstructors() default true;}

用法为:

@Entity(nameInDb="persion ",active=false)

注意:注解方式不支持多schema,但java库形式支持。

基础属性注解

@Id:对象id,通过设置@Id(autoincrement = true)表示自增,只有当Long/long时才有效

@Property:设置成员属性名(表的列名),如果不设置此属性表示默认是类成员名

@NotNull :表示此成员属性非空

@Transient:标识这个字段是自定义的,不会创建到数据库表中

自定义类型

@Convert:如果有自定义的成员类型,使用此注解。如果自定义类型或转换器是在此实体类外,需要设置她们为静态的。
使用实例:

@Entitypublic class User {    @Id    private Long id;    //注解中converter指向类型类,columnType指向在此表中显示的字段类型     @Convert(converter = RoleConverter.class, columnType = String.class)    private Role role;    enum Role {        DEFAULT, AUTHOR, ADMIN    }    static class RoleConverter implements PropertyConverter<Role, String> {        @Override        public Role convertToEntityProperty(String databaseValue) {            return Role.valueOf(databaseValue);        }        @Override        public String convertToDatabaseValue(Role entityProperty) {            return entityProperty.name();        }    }}

索引注解

@Index:为数据库中此列设置为索引列,通过其name参数指定此列的索引名,通过unique参数给索引添加约束 。
@Unique:给索引添加约束。

关系注解

@ToOne:声明与另一个实体的关系:一对一。参数joinProperty 指向另一个实体的 ID列,如果不设置,则默认为id主键:

@Entitypublic class Order {    @Id private Long id;    private long customerId;    @ToOne(joinProperty = "customerId")    private Customer customer;}@Entitypublic class Customer {    @Id private Long id;}

@ToMany:声明与另外多个实体的关系:一对多。这种关系映射有三种情况:
referencedJoinProperty 参数:外键属性,指向另一实体的ID列:

@Entitypublic class User {    @Id private Long id;    @ToMany(referencedJoinProperty = "ownerId")    private List ownedSites;}@Entitypublic class Site {    @Id private Long id;    private long ownerId;}

joinProperties 参数:对于更复杂的关系,可以使用多个@JoinProperty:

@Entitypublic class User {    @Id private Long id;    @Unique private String authorTag;    @ToMany(joinProperties = {            @JoinProperty(name = "authorTag", referencedName = "ownerTag")    })    private List ownedSites;}@Entitypublic class Site {    @Id private Long id;    @NotNull private String ownerTag;}

@JoinEntity:多对多的关系:

@Entitypublic class Site {    @Id private Long id;    @ToMany    @JoinEntity(            entity = JoinSiteToUser.class,            sourceProperty = "siteId",            targetProperty = "userId"    )    private List authors;}@Entitypublic class JoinSiteToUser {    @Id private Long id;    private Long siteId;    private Long userId;}@Entitypublic class User {    @Id private Long id;}

@Generated代码

@Generated 这个是build后greendao自动生成的,这个注解理解为防止重复,每一块代码生成后会加个hash作为标记。 官方不建议你去碰这些代码,改动会导致里面代码与hash值不符。如果手动改变引发错误:

Error:Execution failed for task ':app:greendao'.> Constructor (see ExampleEntity:21) has been changed after generation.Please either mark it with @Keep annotation instead of @Generated to keep it untouched,or use @Generated (without hash) to allow to replace it.

当这个错误出现时,通常有两种方法解决:
1>恢复@Generated注解的代码,可以删除此段代码,下次build时,会再重新生成。
2>使用@Keep注解代替@Generated注解,它会告诉greenDAO不去触碰@Keep注解的代码。

操作数据库

在Android项目中自定义一个Application:

public class App extends Application {    /** 数据库是否加密的标识 */    public static final boolean ENCRYPTED = true;    private DaoSession daoSession;    @Override    public void onCreate() {        super.onCreate();        //创建数据库        DevOpenHelper helper = new DevOpenHelper(this, ENCRYPTED ? "notes-db-encrypted" : "notes-db");        //获取数据库读写的权限,如果进行加密调用helper.getEncryptedWritableDb("super-secret"),参数为设置的密码        Database db = ENCRYPTED ? helper.getEncryptedWritableDb("super-secret") : helper.getWritableDb();        daoSession = new DaoMaster(db).newSession();    }    public DaoSession getDaoSession() {        return daoSession;    }}

在Manifest文件中指向自定义的Application:

    ".App"        ...    

对数据库加密

在build.gradle中添加依赖:

dependencies {    compile 'net.zetetic:android-database-sqlcipher:3.5.1'}

如上App类,对数据库进行加密读写:

//创建数据库(上下文,数据库名)DevOpenHelper helper = new DevOpenHelper(this,"notes-db-encrypted");//获取读写(密码)Database db = helper.getEncryptedWritableDb("super-secret")

如果只要求对加密的数据库进行读的操作:

//获取读(密码)Database db = helper.getEncryptedReadableDb("super-secret")

DaoMaster和DaoSession

DaoMaster:是使用greenDAO的入口点,DaoMaster为指定的schema保存数据库对象(SQLiteDatabase)并且管理DAO类(不是对象类)。它内部的静态方法可以用来创建表或删除表,它的内部类OpenHelper 和 DevOpenHelper 是 SQLiteOpenHelper在数据库中创建schema的实现。
DaoSession:也是使用greenDAO的重要类,为指定的schema管理所有可用的DAO对象,可以使用getter方法获得DAO对象。DaoSession还提供了一些通用的持久性的方法,如插入,装载,更新,刷新和删除实体。
如果要对数据库进行操作,需要先获取相关实体类Dao对象:

daoMaster = new DaoMaster(db);daoSession = daoMaster.newSession();persionDao = daoSession.getPersionDao();

请注意,该数据库连接属于DaoMaster,所以多个Session指向的是同一个数据库。新的Session可以相当迅速的创建。每个Session都分配内存,通常为实体的一个Session“缓存”。
如果有对同一个数据库对象的多个请求,会有几个java对象来处理?这取决于作用域,默认(如果不对他进行配置)是这多个请求会返回同一个java对象,比如,查询USER 表的 ID 42 获取User对象,会为每一个请求返回相同的结果。并且会将其缓存在内存中。如果一个实体仍然存在内存中(greenDAO对它有弱引用),该实体将不会是从数据库值再次获得,例如,如果通过其ID加载实体,但是之前已经加载过这个实体,greenDAO就不会再次询问数据库了,它会从session缓存“马上”返回此对象,这样更快一个或两个数量级。

操作

1>获取DAO

        // get the note DAO        DaoSession daoSession = ((App) getApplication()).getDaoSession();        persionDao = daoSession.getPersionDao();

2>插入数据:id设为null,数据库会自动为其分配自增的id:

        Persion persion = new Persion(null, "liHua", 5);        persionDao.insert(persion);

3>保存数据:如果key属性不为null,会更新这个对象;如果为null,会插入这个对象:

        Persion persion = new Persion(2, "liHua", 5);        persionDao.save(persion);

4>查询数据:

Persion persion = persionDao.queryBuilder().where(PersionDao.Properties.Name.eq("LiHua")).build().unique();

unique()表示查询结果为一条数据,若数据不存在,persion为null。如果多个获取多个查询结果:

List persionList = persionDao.queryBuilder()         .where(PersionDao.Properties.Id.notEq(10)) //查询条件        .orderAsc(PersionDao.Properties.Id) //按首字母排列        .limit(10)  //限制查询结果个数       .build().list(); //结果放进list中

5>删除数据:

persionDao.delete(persion);//或persionDao.deleteByKey(persion.getId()); 

6>事务:当执行的数据较多时,可以使用事务处理,事务的方法有insertInTx(~),saveInTx(~)等后缀为-InTx的方法,其参数为多个对象:

        Persion persion = new Persion(2, "liHua", 5);        Persion persion1 = new Persion(2, "liHua", 5);        Persion persion2 = new Persion(2, "liHua", 5);        persionDao.saveInTx(persion,persion1,persion2);

7>更多使用方法参考greendao库中AbstractDao类。

更多参考greenDAO: Android ORM for your SQLite database

更多相关文章

  1. 深入分析安卓(Android)中的注解
  2. Android(安卓)如何编写基于编译时注解的项目
  3. Android(安卓)存储学习之SQLite数据库的基本操作
  4. android直接读取项目中的sqlite数据库
  5. Android(安卓)Sqlite数据库查询或删除N天前数据
  6. 从零开始学习Android(二)从架构开始说起
  7. Android(安卓)GreenDao实现CRUD和升级详解
  8. android之存储篇——SQLite数据库
  9. Android提高第八篇之SQLite分页读取

随机推荐

  1. Android中的绘图
  2. android 横屏显示
  3. Android Parcelable的使用
  4. android 学习 之 prefernce
  5. 将TabHost选项卡置于下方
  6. Android Studio ------Dynamic layout pr
  7. android小项目
  8. Android 圆角矩形
  9. android中颜色对应的值
  10. Button去掉自带的阴影效果