GreenDao详解

GreenDao

介绍

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

这里写图片描述

特点

1.最大的性能,可能是android中最快ORM Database解决方案

2.易使用,只需要定义data model,GreenDao会构建data objects(Entities)和DAOS(data access objects)

3.最少的内存开销

4.依赖的库很小,< 100kb

5.支持数据加密

6.强大的社区

官方给出的性能对比

这里写图片描述

GreenDao配置

// In your root build.gradle file:
buildscript {
    repositories {
        jcenter()
        mavenCentral() // add repository
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.3.0'
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
    }
}

// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin

dependencies {
    compile 'org.greenrobot:greendao:3.2.2' // add library
}

核心类

这里写图片描述

1.DaoMaster

这个类是使用greenDao的入口,DaoMaster持有着SQLite数据库对象并管理着所有一个schema中的所有Dao类。它有一些静态方法用来创建表和删除表,它的内部类OpenHelper和DevOpenHelper继承自SQLiteOpenHlper用来在SQLite中创建schema

2.DaoSession

管理了一个schema中的所有Dao对象,可以通过getter方法获取这些Dao对象。DaoSession提供entity的一些持久化方法如insert,load,update,refresh,delete,这些方法都是由插件自动生成的

3.DAOS

Data access objects简称Dao,用来对entity的存取访问。针对每一个entity,greendao都会生成一个对应的DAO类,这些类提供了比DaoSession更多的持久化方法,如count,loadAll等

4.Entity

持久化类,通常情况下一个持久化类对应着数据库中的一张表,每条数据对应着普通的pojo类或者javabean

注意了,DaoMaster,Daosession,DAOS类是默认没有的,我们需要先编写一个Entity,而Entiry的内容也只是需要编写成员变量,然后Build->makeProject,上面四个核心类就会自动构建出来,Entity的内容也会自动完善好。

GreenDao使用

官网引导

ToOne ToMany的关系介绍

@Entity
public class Order {
    @Id private Long id;

    private long customerId;

    @ToOne(joinProperty = "customerId")
    private Customer customer;
}

@Entity
public class Customer {
    @Id private Long id;
}

@Entity
public class Customer {
    @Id private Long id;

    @ToMany(referencedJoinProperty = "customerId")
    @OrderBy("date ASC")
    private List<Order> orders;
}

@Entity
public class Order {
    @Id private Long id;
    private Date date;
    private long customerId;
}

1.此时使用OrderDao的queryBuilder进行查询,默认是不会蒋Customer的数据加载进来的,只有在使用了getCustomer方法时,才会将数据加载进来,这样当不需要Customer数据时,可以很快的进行加载。

2.但是如果我需要在查询的时候就将Customer的数据加载进来,那么就要使用queryDeep方法了。queryDeep的第一个参数就是where的内容,第二个参数就是第一个参数中使用了?表示的数据,通配符数据,可以使用数组。在这里需要注意,where中使用到的 “表名.字段名” ,表名不能使用OrderDao.TABLENAME,因此在底层的查询数据中,已经将这个表名换了一个别名,在本表中,表名换成了T,ToOne,ToMany关联的表,根据顺序定义别名T0,T1,T2,以此类推。

loadDeep举例

 List<Student> students = mStu.queryDeep("where T." + StudentDao.Properties.Name.columnName + " = ?" 
 + " and T." + StudentDao.Properties.Age.columnName + " > ?", new String[]{stuName, age + ""});

实际性能测试

测试的表内容

Student表 (学生)

    @Id(autoincrement = true)
    private Long id;

    private String name;

    private Integer age;

    private long subjectid;

    @ToOne(joinProperty = "subjectid")
    private Subject subject;

Subject表(课程)

    @Id(autoincrement = true)
    private Long id;

    private String name;

    private String teacher;

操作 耗时/单位:毫秒
批量插入Subject 10000 269
批量插入Student 10000,每个student对应一个Subject 224
批量插入Student 10000,共用一个Subject 253
逐个插入Subject,10000条 31568
在表Subject中60006条单个条件查找 20
在表Subject中60006条2个条件查找 14
在表Student中40009条单条件查找 32
在表Student中40009条2个条件查找 8
在表Subject中60009条单条件删除 47
在表Subject中60008条2条件删除 29
操作 耗时/单位:毫秒
在表Student中40009条1条件删除 23
在表Student中40007条2条件删除 40
在表Student中41005条2条件删除 25
在表Subject中60310条批量更新300条 104
在表Student中41505条批量更新500 85

经过测试,GreenDao的性能确实很好。

GreenDao多表关联

外键使用

建表

建立三张表,Student、Subject、Teacher。一个学生上一门课,一门课对应多个老师。因此Student有一个外键指向Subject,Subject有一外键指向老师。这里就是简单演示了多表。

Student:

    @Id(autoincrement = true)
    private Long id;

    @Property(nameInDb = "NAME")
    private String name;

    @Property(nameInDb = "PHONE")
    private String phone;

    private long subjectId;

    @ToOne(joinProperty = "subjectId")
    private Subject subject;

Subject:

    @Id(autoincrement = true)
    private Long id;

    @Property(nameInDb = "NAME")
    private String name;

    @Property(nameInDb = "PLACE")
    private String place;

    private long teacherId;

    @ToOne(joinProperty = "teacherId")
    private Teacher teacher;

Teacher:

    @Id(autoincrement = true)
    private Long id;

    @Property(nameInDb = "NAME")
    private String name;

    @Property(nameInDb = "ADDRESS")
    private String address;

底层语句

看看使用GreenDao设置外键关联其他表时,它的sql语句是如何写的。

看Student表的创建,Stuent表关联了Subject表

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

Subject表,Subject 表关联了Teacher

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

通过底层代码的查看。发现他没有使用Foreign Key字样。只是让外键的属性和关联表的主键属性一样。

为什么呢?

其实想想,原因是,设置外键的作用是在插入时确保外键关联的属性是存在的。而在GreenDao中,id属性的获取是通过对象getId()获取。而且必须要将它插入了才可以获取到id属性值,所以在传递外键的属性时,已经确保了外键关联数据的存在。如果不存在明显获取的外键属性的关联对象就是null。所以在使用时进行判断比较稳妥。

插入

Student

id name phone subjectid
1 xiaoming 123456 1
2 xiaohua 123456 2
3 xiaoqiang 123456 3

Subject

id name place teacherid
1 math place math1 1
2 english place english 2
3 math place math2 3

Teacher

id name address
1 zhangsan zhangsan address
2 wangwu wangwu address
3 lisi lisi address

代码插入:

       //插入老师
        Teacher teacher1 = new Teacher(null, "zhangsan", "place zhangsan");
        Teacher teacher2 = new Teacher(null, "wangwu", "place wangwu");
        Teacher teacher3 = new Teacher(null, "lisi", "place lisi");


        mTeaDao.insert(teacher1);
        mTeaDao.insert(teacher2);
        mTeaDao.insert(teacher3);


        //插入课程
        Subject subject1 = new Subject(null,"math","place math1 ",teacher1.getId());
        Subject subject2 = new Subject(null,"english","place english",teacher2.getId());
        Subject subject3 = new Subject(null,"math","place math2",teacher3.getId());

        mSubDao.insert(subject1);
        mSubDao.insert(subject2);
        mSubDao.insert(subject3);

        //插入学生
        Student student1 = new Student(null, "xiaoming", "123456", subject1.getId());
        Student student2 = new Student(null, "xiaohua", "23456", subject2.getId());
        Student student3 = new Student(null,"xiaoqiang","34567",subject3.getId());

        mStuDao.insert(student1);
        mStuDao.insert(student2);
        mStuDao.insert(student3);

join查询

join介绍

关联查询使用join

需要查询什么表的信息使用相关表的xxxDao对象,创建QueryBuilder.使用join关联其他表。

将相关联的表的属性通过join传入即可。

/**
  * Expands the query to another entity type by using a JOIN.
  * The primary key property of the primary entity for
  * this QueryBuilder is used to match the given destinationProperty.
  */
public <J> Join<T, J> join(Class<J> destinationEntityClass, Property destinationProperty)

/**
 * Expands the query to another entity type by using a JOIN.
 * The given sourceProperty is used to match the primary
 * key property of the given destinationEntity.
 */
public <J> Join<T, J> join(Property sourceProperty, Class<J> destinationEntityClass)

/**
 * Expands the query to another entity type by using a JOIN.
 * The given sourceProperty is used to match the given
 * destinationProperty of the given destinationEntity.
 */
public <J> Join<T, J> join(Property sourceProperty, Class<J> destinationEntityClass,
    Property destinationProperty)
/**
 * Expands the query to another entity type by using a JOIN.
 * The given sourceJoin's property is used to match the
 * given destinationProperty of the given destinationEntity.
 * Note that destination entity of the given join is used
 * as the source for the new join to add. In this way,
 * it is possible to compose complex "join of joins" across
 * several entities if required.
 */
public <J> Join<T, J> join(Join<?, T> sourceJoin, Property sourceProperty,
    Class<J> destinationEntityClass, Property destinationProperty)

查询 课程是math,老师是zhangsan的学生信息

        QueryBuilder<Student> studentQueryBuilder = mStuDao.queryBuilder();
        Join josinSubject = studentQueryBuilder.join(StudentDao.Properties.SubjectId, Subject.class, SubjectDao.Properties.Id);
        Join joinTeacher = studentQueryBuilder.join(josinSubject, SubjectDao.Properties.TeacherId, Teacher.class, TeacherDao.Properties.Id);
        joinTeacher.where(TeacherDao.Properties.Name.eq("zhangsan"));
        List<Student> list = studentQueryBuilder.list();

查询教数学的老师信息

        QueryBuilder<Teacher> teacherQueryBuilder = mTeaDao.queryBuilder();
        Join<Teacher, Subject> join = teacherQueryBuilder.join(TeacherDao.Properties.Id, Subject.class, SubjectDao.Properties.TeacherId);
        join.where(SubjectDao.Properties.Name.eq("math"));
        List<Teacher> list = teacherQueryBuilder.list();
        if (list.isEmpty()) {
            Log.i("student","no data");
        }
        for (Teacher teacher : list) {
            Log.i("student",teacher.getName()+"  "+teacher.getAddress());
        }

session 缓存

如果你有多个相同的查询语句去执行,猜猜看返回给你的对象是一个还是多个?比如说像下面这样

QueryBuilder<Project> projectQueryBuilder = projectDao
                .queryBuilder()
                .where(ProjectDao.Properties.UserName.eq("123456"));
Query<Project> query = projectQueryBuilder.build();
Project project1=query.unique();
QueryBuilder<Project> projectQueryBuilder1 = projectDao
                .queryBuilder()
                .where(ProjectDao.Properties.UserName.eq("123456"));
Query<Project> query2 = projectQueryBuilder1.build();
Project project2=query.unique();

答案是project1==project2而且project2查询出来的速度要比project1查询出来的速度快很多倍;

这是因为在同一个session中如果一个entities已经被session记录那么下一次再次操作该实体时,greenDao会先从内存中查找,如果内存中没有再去数据库中查找。这样一方面就极大的提高greenDao的查询效率,另一方面也是需要特别注意的是当entities更新过 greenDao仍然会从内存中取出旧值,所以如果entities更新过,需要去调用daoseesion.clear()方法清除缓存后才能查到最新值,否则查询到的将还是保存在内存中的值。

下面介绍下清除缓存有两种方法

清除所所有的缓存

daoSession.clear();

清除指定Dao类的缓存

projectDao = daoSession.getNoteDao();
projectDao.detachAll();

GreenDao数据库升级

GreenDao默认数据库升级方式

将原来的表全部删掉,重新创建新表

在DaoMaster类里面的静态内部类

    /** WARNING: Drops all table on Upgrade! Use only during development. */
    public static class DevOpenHelper extends OpenHelper {
        public DevOpenHelper(Context context, String name) {
            super(context, name);
        }

        public DevOpenHelper(Context context, String name, CursorFactory factory) {
            super(context, name, factory);
        }

        @Override
        public void onUpgrade(Database db, int oldVersion, int newVersion) {
            Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
            dropAllTables(db, true);
            onCreate(db);
        }
    }

还记得我们怎么初始化数据库的吗。就是使用这个DevOpenHelper

        DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this,"Test");
        Database db = helper.getWritableDb();
        mDaoSession = new DaoMaster(db).newSession();

这种方式是不可能使用在发布的产品上的,因为会导致原来的数据丢失。因此我们必须要实现我们自己的更新方式。因此现在首要的就是创建自己的DevOpenHelper类。

public class MvDevOpenHelper extends DaoMaster.OpenHelper
{
    public MvDevOpenHelper(Context context, String name) {
        super(context, name);
    }

    public MvDevOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);

    }

    @Override
    public void onCreate(Database db) {
        super.onCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        super.onUpgrade(db, oldVersion, newVersion);
        //TODO 编写自己的数据库更新方式

        //方式1,一步一步的实现更新,更具oldversion和newVersion


        //方式2 一步到位


    }
}

此时在App中的创建数据库就要使用我们自定义的MvDevOpenHelper对象了。

        MvDevOpenHelper helper = new MvDevOpenHelper(this,"Test");
        Database db = helper.getWritableDb();
        mDaoSession = new DaoMaster(db).newSession();

使用Sql语句、逐步升级

可以根据旧版本号和新版本号,进行逐步更新。使用switch

例如:

        switch (oldVersion) {
            case 1:
                //更改数据库
            case 2:
                //更改数据库
            case 3:
                //更改数据库
                break;
        }

此时使用switch中,对于曾今的低版本数据库中的case,不需要进行break。知道最新的版本。因为我们要按照 1 -> 2 , 2 -> 3,……的方式,让其更新到最新的版本。

一步到位

这是另一种方式,直接更新到最新的版本。

步骤是这样的

1.首先根据旧版本的数据表创建临时表

2.将旧表删除

3.创建新表

4.将临时表中的数据重新拷贝到新表,将有的属性进行拷贝,新增的为null,删除的不赋值

5.删除临时表

代码是这样的

public class MigrationHelper {
    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

    public static MigrationHelper getInstance() {
        if (instance == null) {
            instance = new MigrationHelper();
        }
        return instance;
    }

    private static List<String> getColumns(Database db, String tableName) {
        List<String> columns = new ArrayList<>();
        Cursor cursor = null;
        try {
            cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
            if (cursor != null) {
                columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
            }
        } catch (Exception e) {
            Log.v(tableName, e.getMessage(), e);
            e.printStackTrace();
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return columns;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        generateTempTables(db, daoClasses);
        DaoMaster.dropAllTables(db, true);
        DaoMaster.createAllTables(db, false);
        restoreData(db, daoClasses);
    }

    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String divider = "";
            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList<>();

            StringBuilder createTableStringBuilder = new StringBuilder();

            createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tableName).contains(columnName)) {
                    properties.add(columnName);

                    String type = null;

                    try {
                        type = getTypeByClass(daoConfig.properties[j].type);
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }

                    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

                    if (daoConfig.properties[j].primaryKey) {
                        createTableStringBuilder.append(" PRIMARY KEY");
                    }

                    divider = ",";
                }
            }
            createTableStringBuilder.append(");");
            Log.i("lxq", "创建临时表的SQL语句: " + createTableStringBuilder.toString());
            db.execSQL(createTableStringBuilder.toString());

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(" FROM ").append(tableName).append(";");
            Log.i("lxq", "在临时表插入数据的SQL语句:" + insertTableStringBuilder.toString());
            db.execSQL(insertTableStringBuilder.toString());
        }
    }

    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
        for (int i = 0; i < daoClasses.length; i++) {
            DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

            String tableName = daoConfig.tablename;
            String tempTableName = daoConfig.tablename.concat("_TEMP");
            ArrayList<String> properties = new ArrayList();
            ArrayList<String> propertiesQuery = new ArrayList();
            for (int j = 0; j < daoConfig.properties.length; j++) {
                String columnName = daoConfig.properties[j].columnName;

                if (getColumns(db, tempTableName).contains(columnName)) {
                    properties.add(columnName);
                    propertiesQuery.add(columnName);
                } else {
                    try {
                        if (getTypeByClass(daoConfig.properties[j].type).equals("INTEGER")) {
                            propertiesQuery.add("0 as " + columnName);
                            properties.add(columnName);
                        }
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }

            StringBuilder insertTableStringBuilder = new StringBuilder();

            insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
            insertTableStringBuilder.append(TextUtils.join(",", properties));
            insertTableStringBuilder.append(") SELECT ");
            insertTableStringBuilder.append(TextUtils.join(",", propertiesQuery));
            insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

            StringBuilder dropTableStringBuilder = new StringBuilder();

            dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
            Log.i("lxq", "插入正式表的SQL语句:" + insertTableStringBuilder.toString());
            Log.i("lxq", "销毁临时表的SQL语句:" + dropTableStringBuilder.toString());
            db.execSQL(insertTableStringBuilder.toString());
            db.execSQL(dropTableStringBuilder.toString());
        }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
        if (type.equals(String.class)) {
            return "TEXT";
        }
        if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class) || type.equals(int.class)) {
            return "INTEGER";
        }
        if (type.equals(Boolean.class) || type.equals(boolean.class)) {
            return "BOOLEAN";
        }

        Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
        exception.printStackTrace();
        throw exception;
    }
}

然后的我们自定义的MvDevOpenHelper中使用这个MigrationHelper进行更新。

  MigrationHelper.getInstance().migrate(db,StudentDao.class,SubjectDao.class);

只要将要更改的xxxDao表对象传递进行即可。

实验发现可行。

GreenDao懒加载

  1. LazyList - 懒加载的方式,即实体按照需求加载进入内存(查询完不会立即加载到内存中,只有在需要数据的时候也就是遍历这个LazyList的时候,才会加载到内存中),列表中的元素在第一次访问时候就会同时缓存在一个ArrayList集合中,它再次访问这些元素则直接从集合中拿。如果你不想缓存这些数据又想懒加载,可以通过Query的listLazyUncached()方法。这个集合在使用完毕必须close,即调用:listLazy.close();
  2. queryBuilder,对于有ToOne ToMany属性的数据,其实也是懒加载方式,当未使用到这个关联的对象时,是不会加载的,使用时再会进行加载。如果想要一查询就将数据加载,那么可以使用queryDeep。

QueryDeep使用注意:

GreenDao+多线程

GreenDao多线程之改变数据库结构

对于insert,update,delete等会改变数据库的操作,GreenDao底层都是进行了同步。

看代码AbstractDao.java文件

    /**
     * Insert an entity into the table associated with a concrete DAO.
     *
     * @return row ID of newly inserted entity
     */
    public long insert(T entity) {
        return executeInsert(entity, statements.getInsertStatement(), true);
    }

进入executeInsert方法

    private long executeInsert(T entity, DatabaseStatement stmt, boolean setKeyAndAttach) {
        long rowId;
        if (db.isDbLockedByCurrentThread()) {
            rowId = insertInsideTx(entity, stmt);
        } else {
            // Do TX to acquire a connection before locking the stmt to avoid deadlocks
            db.beginTransaction();
            try {
                rowId = insertInsideTx(entity, stmt);
                db.setTransactionSuccessful();
            } finally {
                db.endTransaction();
            }
        }
        if (setKeyAndAttach) {
            updateKeyAfterInsertAndAttach(entity, rowId, true);
        }
        return rowId;
    }

进入insertInsideTx方法

    private long insertInsideTx(T entity, DatabaseStatement stmt) {
        synchronized (stmt) {
            if (isStandardSQLite) {
                SQLiteStatement rawStmt = (SQLiteStatement) stmt.getRawStatement();
                bindValues(rawStmt, entity);
                return rawStmt.executeInsert();
            } else {
                bindValues(stmt, entity);
                return stmt.executeInsert();
            }
        }
    }

可以看到都是进行了同步操作的。

同理可以看update,delete。

GreenDao多线程之查询

有时我们希望在多线程中执行查询。从greenDAO 1.3版本开始,实例化Query对象均会绑定到其自己的线程,这样我们就可以安全的设置Query参数,因为其他线程无法影响到。如果其他线程使用别的线程的query(比如设置参数、执行查询)将会抛出异常。因此,我们也不需要做同步工作,而且不要加锁,因为加入相关的事务用到了该Query对象将导致死锁。

为完全地避免可能产生的死锁,1.3版本引入了forCurrentThread()方法。该方法将返回本线程内的Query实例,每次调用该方法时,参数均会被重置为最初创建时的一样。

        Query<Student> xiaoming = mStuDao.queryBuilder().where(StudentDao.Properties.Name.eq("xiaoming")).build().forCurrentThread();

GreenDao与SqLite一起

共用数据库db文件

实际上GreenDao只是在原生。的SqLite操作上面封装了一层,真正的实现还是SqLite。

所以底层的数据库文件是一样的。因此这样就可以和SqlIte共同存在,共同使用同一个db,可以共同对db进行操作。

使用GreenDao创建的数据库,对于String都属性底层都是创建为TEXT。

不过对于底层是VARCHAR类型的字段,在GreenDao中使用String,一样也是可以的。

所以使用GreenDao可以做到完全不用更改原来的数据库,直接操作原来的db。完美和SqlLite兼容。但是必须得保证数据库名一样,表一样,字段一样。

GreenDao数据库备份

对于GreenDao数据库的备份。

首先我们要备份db文件。

再次就是备份我们创建的Entity,也就是关联表的实体。只要知道实体,可以使用GreenDao自动生成DaoMaster,DaoSeeion,XXXXDao类等。

结束

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值