Android base development library to make development easier. DevRing & Demo address: github.com/LJYcoder/De…

Study/Reference address: http://www.jianshu.com/p/4e6d72e7f57a http://blog.csdn.net/qq_30379689/article/details/54410838 http://blog.csdn.net/shineflowers/article/details/53405644

preface

I used GreenDAO when I was choosing a database framework, but I didn’t use it because it was cumbersome to configure and required me to create Java libraries. But now, with version 3.0, GreenDAO has become a more popular ORM solution, thanks to its simplified usage process, fast access, small size, cache support, and encryption support.

Attached is an official comparison of GreenDAO, OrmLite and ActiveAndroid


introduce

The following is divided into configuration, database building table, add, delete, change, encryption, upgrade, confusion these parts to introduce.

1. The configuration

1.1 Adding a Dependency

Add the build.gradle file under Project

dependencies {
    / / greendao configuration
    classpath 'org. Greenrobot: greendao - gradle - plugin: 3.2.0'
}
Copy the code

Add the build.gradle file under Module

apply plugin: 'org.greenrobot.greendao'

dependencies {
	/ / greenDAO configuration
	compile 'org. Greenrobot: greendao: 3.2.0'
}
Copy the code

1.2 Setting the version number and generation path

android {
    / / greendao configuration
    greendao {
        // Database version, changed during the upgrade
        schemaVersion 1
        // Generated DAO, DaoMaster, and DaoSession package paths. By default, the package path is the same as that of the table entity
        daoPackage 'com.dev.base.model.db'
        // Generate the source file path. The default source file directory is in the build directory (build/generated/source/greendao)
        targetGenDir 'src/main/java'}}Copy the code


2. Build database and table

2.1 Creating a Database

//DaoMaster is a class that is automatically generated after the table entities are created.
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this."test.db".null);
Copy the code

2.2 Creating a Data table

GreenDAO creates data tables using Object Relation Mapping (ORM). That is, create an entity class that maps the entity structure to the structure of a data table. The following shows how to create a “movie Favorites” data table. There are two steps: create table entities and Make Project generates code.

2.2.1 Creating table entities

@Entity
public class MovieCollect {

    @Id
    private Long id;
    private String movieImage;
    private String title;
    private int year;
    
}
Copy the code

Annotation is introduced: (refer to the http://www.jianshu.com/p/4e6d72e7f57a)

@entity is used to declare a class Entity, indicating that it will be mapped to a data table. The @entity () parentheses can add more detailed Settings, such as: NameInDb = “TABLE_NAME” ——> Declare the table name of the table, default class name createInDb = true ——> Whether to create the table, GenerateConstructors = true ——> Whether to generate a constructor with all parameters, Default true generateGettersSetters = true ——> Whether to generate getters/setters, default true

Autoincrement = true the @id is used to declare a variable as the primary key of a table, and the type Long @id () parentheses are used to add autoincrement = true

@unique is used to declare that the value of a variable must be Unique

@notnull is used to declare that a variable cannot be null

@property @property (nameInDb = “URL”) is used to declare the actual field name of a variable in the table URL

@TRANSIENT is used to declare that a variable is not mapped to the table

ToOne and ToMany are used to declare one-to-one and one-to-many relationships. Here are some examples:

  • One-to-many relationship between students and schools (one student to one school, one school to many students)
@Entity
class Student{
	/ /... Omit other variables
	private long fk_schoolId;/ / foreign key
	
	@ToOne(joinProperty = "fk_schoolId")
	private School school;
}

@Entity
class School{
	/ /... Omit other variables
	@ToMany(referencedJoinProperty = "fk_schoolId")
    private List<Student> students;
}
Copy the code
  • The ** many-to-many ** relationship between students and courses (one student should have multiple courses, one course should have multiple students)
@Entity
class Student{
	/ /... Omit other variables
	@ToMany
	@JoinEntity(
            entity = StudentWithCourse.class,
            sourceProperty = "sId",
            targetProperty = "cId"
    )
    private List<Course> courses;
}

@Entity 
class Course{
	/ /... Omit other variables
	@ToMany
	@JoinEntity(
            entity = StudentWithCourse.class,
            sourceProperty = "cId",
            targetProperty = "sId"
    )
    private List<Course> courses;
}

@Entity
class StudentWithCourse{
	@Id
    private Long id;
    private Long sId;
    private Long cId;
}
Copy the code

2.2.2 Make Project

After the table entities are written using the above annotations, recompiling the Project through Build– >Make Project automatically generates constructors and getter/setter methods in the table entities. In addition, DaoMaster, DaoSession, and daOs corresponding to table entities (such as MovieCollectDao) are generated in the specified (or default) package.

DaoMaster: used to create database and obtain DaoSession DaoSession: used to obtain Dao corresponding to each table Dao: provides methods for adding, deleting, modifying, and checking tables

3. Add, delete, modify and check

To add, delete, change, and check the data table, it is necessary to obtain the Dao class corresponding to the table, and obtaining the Dao class requires DaoSession. Create a DaoManager to initialize the database and provide DaoSession.

/ / DaoManager in code

// Get DaoSession to get the operation DAO classes for each table
public DaoSession getDaoSession(a) {
    if (mDaoSession == null) {
        initDataBase();
    }
    return mDaoSession;
}

// Initialize the database and related classes
private void initDataBase(a){
    setDebugMode(true);// Log printing is enabled by default
    mSQLiteOpenHelper = new DaoMaster.DevOpenHelper(MyApplication.getInstance(), DB_NAME, null);/ / build library
    mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
    mDaoSession = mDaoMaster.newSession();
    mDaoSession.clear();// Clear the cache of all tables
}

// Whether to enable Log
public void setDebugMode(boolean flag) {
    MigrationHelper.DEBUG = true;// To view database update logs, set this parameter to true
    QueryBuilder.LOG_SQL = flag;
    QueryBuilder.LOG_VALUES = flag;
}
Copy the code

Obtain the Dao corresponding to the target table via DaoSeesion, and then start the add, delete, alter, and query operations.

MovieCollectDao mMovieCollectDao = DaoManager.getInstance().getDaoSession().getMovieCollectDao();
Copy the code

3.1 to add

  • Insert single data
MovieCollect movieCollect;
mMovieCollectDao.insert(movieCollect);
Copy the code
  • Insert a set of data
List<MovieCollect> listMovieCollect;
mMovieCollectDao.insertInTx(listMovieCollect);
Copy the code
  • Insert or replace data
// If the inserted data already exists in the table, replace the old data (based on the primary key to check whether it already exists).

MovieCollect movieCollect;
mMovieCollectDao.insertOrReplace(movieCollect);// Single data

List<MovieCollect> listMovieCollect;
mMovieCollectDao.insertOrReplaceInTx(listMovieCollect);// A set of data
	
Copy the code

3.2 delete

  • Delete single data
MovieCollect movieCollect;
mMovieCollectDao.delete(movieCollect);
Copy the code
  • Delete a set of data
List<MovieCollect> listMovieCollect; MMovieCollectDao. DeleteInTx (listMovieCollect);Copy the code
  • Delete all data
mMovieCollectDao.deleteAll();
Copy the code

3.3 change

  • Modifying a single data
MovieCollect movieCollect;
mMovieCollectDao.update(movieCollect);
Copy the code
  • Modify a set of data
List<MovieCollect> listMovieCollect; MMovieCollectDao. UpdateInTx (listMovieCollect);Copy the code

3.4 check

  • Query all data
List<MovieCollect> listMovieCollect = mMovieCollectDao.loadAll();
Copy the code
  • The number of queries
int count = mMovieCollectDao.count();
Copy the code
  • Conditions of the query

Exact query (where)

// Query the movie named "Shawshank Redemption"
MovieCollect movieCollect = 
mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.eq("Shawshank Redemption.")).unique(); 

// Query movies whose movie year is 2017
List<MovieCollect> movieCollect =
mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.eq(2017)).list(); 
Copy the code

Fuzzy query (like)

// Search for movies whose names contain "legend"
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.like("Legend")).list();

// Search for movies whose names start with "mine"
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Title.like("My %")).list();
Copy the code

Range queries

/ / is greater than the
// Query movies whose movie year is older than 2012
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).list();

// Greater than or equal to
// Query movies whose movie year is greater than or equal to 2012
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.ge(2012)).list();

/ / less than
// Query movies whose movie year is less than 2012
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.lt(2012)).list();

// Less than or equal to
// Query the movies whose movie year is less than or equal to 2012
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.le(2012)).list();

// In the middle
// Query movies whose movie years are between 2012 and 2017
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.between(2012.2017)).list();

Copy the code

Ascending and descending order

// Search for movies whose year is older than 2012 and sort by year in ascending order
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).orderAsc(MovieCollectDao.Properties.Year).list();

// Search for movies whose year is older than 2012 and sort by year in descending order
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().where(MovieCollectDao.Properties.Year.gt(2012)).orderDesc(MovieCollectDao.Properties.Year).list();
Copy the code

and/or

//and
// Query for movies whose movie year is older than 2012 and whose movie name begins with "mine"
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().and(MovieCollectDao.Properties.Year.gt(2012), MovieCollectDao.Properties.Title.like("My %")).list();

//or
// Query movies whose movie year is less than 2012 or older than 2015
List<MovieCollect> movieCollect = mMovieCollectDao.queryBuilder().or(MovieCollectDao.Properties.Year.lt(2012), MovieCollectDao.Properties.Year.gt(2015)).list();
Copy the code

The SQL statement

// Query the movie named "Shy Iron Fist"

/ / using the Dao. Criteriabuilder is (). The where () with WhereCondition. StringCondition SQL query () implementation
Query query =
mMovieCollectDao.queryBuilder()
.where(new WhereCondition.StringCondition("TITLE = ?"."The Shy Fist.")).build();
List<MovieCollect> movieCollect = query.list();

// Implement SQL queries using dao.queryRawCreate ()
Query query = mMovieCollectDao.queryRawCreate("WHERE TITLE = ?"."The Shy Fist.");
List<MovieCollect> movieCollect = query.list();
Copy the code

duplicate removal

// Delete from all table fields
Query query = mMovieCollectDao.queryBuilder().distinct();
List<MovieCollect> movieCollect = query.list();

// By a field, please refer to
String SQL_DISTINCT = "SELECT DISTINCT "+ MovieCollectDao.Properties.Title.columnName+" FROM "+MovieCollectDao.TABLENAME;
Cursor curcor = session.getDatabase().rawQuery(SQL_DISTINCT , null); .Copy the code
  • The cache problem

Since GreenDao has caching enabled by default, when you call query A to retrieve X entity, modify it and update it to the database, and then call query A to retrieve X entity, you will find that the contents of X entity are still the same as before. In fact, your changes have been updated to the database, but the query is cached, so it directly returns the entity from the first query. Solution: Clear the cache before query

// Clear all tables from the cache
DaoSession daoSession = DaoManager.getInstance().getDaoSession();
daoSession .clear();

// Clear a table of cached data
MovieCollectDao movieCollectDao = DaoManager.getInstance().getDaoSession().getMovieCollectDao();
movieCollectDao.detachAll();
Copy the code
  • Query the contents of the.db file. A friend provided the idea, so I directly posted the code screenshots he gave me.

Write the.db file in the asset folder to the.db file in the database folder through the IO stream and pass it in via the DaoMaster constructor. The subsequent query operations are as described above.

4. The encryption

Note: Encryption requires the addition of the SQLCipher library, which is bulky and increases the APK size by about 5M, so it is not recommended if your application does not have high security requirements.

Step 1: Add a library dependency to build.gradle under Module for database encryption.

compile 'net. After: android - database - sqlcipher: 3.5.7'// This parameter needs to be added when using an encrypted database
Copy the code

Step 2: To get DaoSession, use getEncryptedWritableDb(” your password “) to get the operation’s database instead of getWritableDatabase().

mSQLiteOpenHelper = new MySQLiteOpenHelper(MyApplication.getInstance(), DB_NAME, null);/ / build library
mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getEncryptedWritableDb("Your password"));/ / encryption
//mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();
Copy the code

Step 3: Use the DaoSession obtained in the above steps to perform specific table operations. If an exception about so library cannot be loaded is reported after the operation, clean and rebuild the project.

5. Upgrade

In iteration, we often need to update the database, and the default daomaster.devOpenHelper will delete the old table and then create a new table, instead of migrating the old data to the new table, resulting in data loss. This is not desirable in practice, so we need to make adjustments. The following describes how to upgrade the database.

The first step: Create a new class, inherit daomaster.devOpenHelper, override onUpgrade(Database db, int oldVersion, int newVersion), MigrationHelper is used in this method for database upgrades and data migration. Many MigrationHelper online source, here is MigrationHelper in https://github.com/yuweiguocn/GreenDaoUpgradeHelper, it mainly through the creation of a temporary table, Migrate old table data to new table, you can go to see the source code.

public class MyOpenHelper extends DaoMaster.OpenHelper {
    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, name, factory);
    }

    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {

        // Pass the DAO, the database table you want to manage, as the last argument to the method
        MigrationHelper.migrate(db, new MigrationHelper.ReCreateAllTableListener() {

            @Override
            public void onCreateAllTables(Database db, boolean ifNotExists) {
                DaoMaster.createAllTables(db, ifNotExists);
            }

            @Override
            public void onDropAllTables(Database db, boolean ifExists) { DaoMaster.dropAllTables(db, ifExists); } }, MovieCollectDao.class); }}Copy the code

Then use MyOpenHelper instead of daomaster.devOpenHelper to do things like create databases

mSQLiteOpenHelper = new MyOpenHelper(MyApplication.getInstance(), DB_NAME, null);/ / build library
mDaoMaster = new DaoMaster(mSQLiteOpenHelper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();
Copy the code

Step 2: In the table entity, adjust the variables (table fields) in it, usually by adding/deleting/modifying fields. Note: 1) The variable type of the new field or modified field should use the wrapper class of the basic data type, such as Integer instead of int, to avoid errors during the upgrade process. 2) According to the code in MigrationHelper, after the upgrade, new and modified fields are assigned null values by default.

Step 3: Delete the automatically generated constructor and getter/setter methods and rebuild –>Make Project to generate.

Step 4: Change the version number of the database in Build. gradle under Module, schemaVersion, increase by 1, and finally run the APP

Greendao {// Database version number, modified during upgrade SchemSchemSchemSchemSchemSchemSchem2 daoPackage'com.dev.base.model.db'
	targetGenDir 'src/main/java'
}
Copy the code

6. Confused

Add the following to the proGuard-rules. pro file for obfuscation configuration

# greenDAO began
-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.**
# greenDAO end


If you add database encryption as described above, you need to add the following configuration
# sqlCipher Database encryption starts-keep class net.sqlcipher.** {*; } -keep class net.sqlcipher.database.** {*; }# sqlCipher The database encryption is complete
Copy the code