The introduction
- In the process of Android application development, almost every application needs to use the database, and directly use the system
Sqlite
It’s not encrypted when storing data, and when we need to insert multiple typesEntity
When, you need to write how many kinds of add, delete, change, checkSQL
Statement, and then concatenation or reflection conversion, cumbersome degree only wrote brother to know. Therefore, Ummm.. In order not to write blood and to ensure some data security, we prefer to choose an ORM that can encrypt the database and can be used simply. - Why use
GreenDao
? The description of the promotion can be found on the official websiteGreenDao, a brief overview is: thanSqlite
Native faster, encryptable, easier to use, minimal memory consumption, library size less than 100K, etc.EventBus
It’s also written by them. It’s highly reliable. - OK, so we’re going to go through the internal implementation step by step, starting with basic usage, and see what’s going on inside.
The preparatory work
- Environment configuration:
- in
projects#build.gradle
The configuration is as follows.
- in
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com. Android. Tools. Build: gradle: 3.1.1'
classpath 'org. Greenrobot: greendao - gradle - plugin: 3.2.2'}}Copy the code
- in
app#build.gradle
The configuration is as follows.
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
dependencies {
implementation 'org. Greenrobot: greendao: 3.2.2'// Add this implementation if you need to encrypt the database'net. After: android - database - sqlcipher: 3.5.6'
}
Copy the code
-
Next you need to create a Model Entity, and you can’t start using greenDao until at least one Model entry has been created and compiled.
-
generate
Entity
The relevant code- There are ways to generate template codeTwo kinds of:
- Method 1: Write JAVA code and generate it, as shown in the following example:
Public class MyDaoGenerator {public static void main(String[] args) {public static void main(String[] args) {"com.example.laixiaolong.greendaotraning.greenDao.db"); addNote(schema); // addCustomerOrder(schema); New DaoGenerator(). GenerateAll (schema,"./app/src/main/java"); } private static void addNote(Schema schema) { Entity note = schema.addEntity("Note"); // specify the class name // id note.addidProperty (); // The property is the Column field note. AddStringProperty ("title").notNull(); note.addStringProperty("content"); note.addDateProperty("date"); } private static void addCustomerOrder(Schema schema) { Entity customer = schema.addEntity("Customer"); customer.addIdProperty(); customer.addStringProperty("name").notNull(); Entity order = schema.addEntity("Order"); order.setTableName("ORDERS"); // "ORDER" is a reserved keyword order.addIdProperty(); Property orderDate = order.addDateProperty("date").getProperty(); Property customerId = order.addLongProperty("customerId").notNull().getProperty(); order.addToOne(customer, customerId); // One-to-one association ToMany customerToOrders = customer.addTomany (order, customerId); // One-to-many association customerToOrders.setName("orders"); customerToOrders.orderAsc(orderDate); }}Copy the code
- Method 2:use
gradle
Plug-in configuration: inapp#build.gradle
This way will be much more convenient, because we only need to focus onEntity
The compiler will automatically generate the corresponding Dao file.
android { ... } greendao {if the entity or the database table version changes, this value will be increased by 1. The default value is 1 schemaVersion 1 // Specify the package name of the generated DAO, DaoMaster, and DaoSession classes. The default is daoPackage under the Entity package"com.example.laixiaolong.greendaotraning.greenDao.db"// Directory for storing generated classes. The default directory is Build /generated/source/ targetGenDir greendao""./app/src/main/java"// Whether generateTests are generated automaticallyfalse// The path where the unit tests are stored. The default path is targetGenDirTests"src/androidTest/java" } Copy the code
- There are ways to generate template codeTwo kinds of:
-
Here is a simple example of a ChatObject associated with a User:
@Entity
public class User
{
@Id(autoincrement = true)
private Long id;
@Unique
private Long userIncrId;
@NotNull
private String userAccount;
private String userName;
private Long orgId;
private String orgName;
// ...
}
@Entity
public class ChatObject
{
@Id(autoincrement = true) private Long id; private String userIcrId; // One-to-one association @toOne (joinProperty ="userIncrId")
private User user;
}
Copy the code
- Among them
@Entity
Attribute usage is explained as follows:@entity (// If there are multiple diagrams, set the schema parameter to tell greenDao which diagram the Entity belongs to // it can be any name schema ="myschema", // Check whether the entity is "active". Active =true// Specify the name of the table. The default is the entity name nameInDb ="AWESOME_USERS"{@index (value =); // Declare that a column occupies multiple columns"name DESC", unique = true}, // flag whether to generate a table, default istrueIf thefalse, multiple entities will map to a table, or create the table createInDb = outside of greenDaofalseGenerateConstructors = generateConstructors = generateConstructors = generateConstructors =true, // Whether the get and attribute are requiredsetGenerateGettersSetters = is automatically generated for a method when it is missingtrue ) Copy the code
Add, delete, change and check (basic operation)
-
Initialize the
- In the first
Application
Is initialized as follows
public class App extends Application { private DaoSession daoSession; private static App app; @Override public void onCreate() { super.onCreate(); app = this; DevOpenHelper = new daomaster.devOpenHelper (this,"roz-hjjm-db"); daoSession = new DaoMaster(devOpenHelper.getWritableDb()).newSession(); Encrypted Database / / / / using the Database encryptedReadableDb = devOpenHelper. GetEncryptedReadableDb ("123456"); // daoSession = new DaoMaster(encryptedReadableDb).newSession(); } public static App app() { return app; } public DaoSession getDaoSession() { returndaoSession; }}Copy the code
- In the first
-
Add and delete
- use
GreenDao
You can almost get rid of writing by handSql
We do not have to worry about the wrong name of a field, the wrong keyword, the wrong punctuation, so as to achieve our ideas more quickly and robustly. - insert
- The insertion methods are as followsTwo kinds of, includingOrdinary insertAnd the use ofThe transactionBatch insert, the difference between the two can be clearly seen through the following code run results (++ using the emulator run ++), also insert
100
Strip data, if the use of transaction batch inserts, efficiency can be higher3 ~ 4
And if only one insert is needed, then for this example (not excluding other cases), the time of the two is the same, as can be seen:- It is better to concentrate on bulk inserts when there is a large amount of data
- If you only need to insert one, you can choose either one
- The insertion methods are as followsTwo kinds of, includingOrdinary insertAnd the use ofThe transactionBatch insert, the difference between the two can be clearly seen through the following code run results (++ using the emulator run ++), also insert
@Test public void testGreenDaoInsert() { DaoSession daoSession = App.getDaoSession(); UserDao userDao = daoSession.getUserDao(); long start = System.currentTimeMillis(); Insert 100: system. out: -->> INSERT total used:: 83ms //insert 1: system. out: -->>Insert total used:: 3msfor (int i = 0; i < 100; i++) { // insertOrReplace userDao.insertOrReplace(new User() .setFirstName("firstName::" + i) .setLastName("lastName::" + i) .setGender(i % 2 == 0 ? "male" : "female") .setPhoneNum(String.valueOf(SystemClock.elapsedRealtimeNanos())) .setAge(i + 10)); //insert 100: system.out: -->> insert total used:: 26ms //insert 1: system.out: -->>Insert total used:: 3ms /*User[] usersArray = new User[100];for (int i = 0; i < 100; i++) { // insertOrReplace usersArray[i] = new User() .setFirstName("firstName::" + i) .setLastName("lastName::" + i) .setGender(i % 2 == 0 ? "male" : "female") .setPhoneNum(String.valueOf(SystemClock.elapsedRealtimeNanos())) .setAge(i + 10) ; } userDao.insertOrReplaceInTx(usersArray); */ System.out.println(String.format("-->>Insert total used:: %sms" , (System.currentTimeMillis() - start)) ); } Copy the code
- Modify the
- The modification process is also very simple, and can be single modification and use transaction batch modification, and the insert method is consistent, butOne thing to note:
- The id (key) of the item to be modified must be set. Otherwise, the modification fails
- The modification process is overridden, meaning that if you modify
Entity
The value of a field innull
, which overwrites the corresponding field data in the table, which is especially important because you can lose your data with a little shake of your hand
- The modification process is also very simple, and can be single modification and use transaction batch modification, and the insert method is consistent, butOne thing to note:
// Modify @test public voidtestGreenDaoUpdate() { DaoSession daoSession = App.getDaoSession(); UserDao userDao = daoSession.getUserDao(); User user = new User() .setId(51L) .setFirstName("horseLai") .setAge(23) .setPhoneNum("1234"); // before: User{id=51, phoneNum='5866201745180', firstName='firstName::7', gender='female', lastName='lastName::7', age=17} // after: User{id=51, phoneNum='1234', firstName='horseLai', gender='null', lastName='null'Userdao.update (user); userdao.update (user); // userdao.updateintx (user); }Copy the code
- delete
- The deletion process is also very simple, there are four ways to carry out, specific can be selected according to need, if you know
id
then1
和3
allok
If the deletion condition needs to be specified, then4
, delete all data2
.
- The deletion process is also very simple, there are four ways to carry out, specific can be selected according to need, if you know
// delete @test public voidtestGreenDaoDelete() { DaoSession daoSession = App.getDaoSession(); UserDao userDao = daoSession.getUserDao(); // 1. Delete a single // userdao.deleteByKey (15L); // 2. DeleteAll userdao.deleteall (); Userdao.deletebykeyintx (15L, 16L,17L); / / 4. Batch (the search terms and conditions) delete userDao. Criteriabuilder is (). The where (userDao. Properties. Age. Gt (15)). BuildDelete () .executeDeleteWithoutDetachingEntities(); }Copy the code
- To find the
- It is also easy to find and can be selected on demand, as is clear in the following example
sql
Statement to query (mode2
) will be much simpler, and the second is how to use it1
Finally, the way of use3
But I don’t think anyone would like to use it that way3
Unless there’s a special need, after all, when you see a bunch of code and you want to walk away from it, you might forget to release itcursor
, causing a memory leak.
- It is also easy to find and can be selected on demand, as is clear in the following example
// find @test public voidtestGreenDaoQuery() { DaoSession daoSession = App.getDaoSession(); UserDao userDao = daoSession.getUserDao(); /*List<User> users = userdao.queryBuilder ().limit(10).orderasc (userDao.properties.age) .where(UserDao.Properties.Age.gt(15)) .build() .list(); /*List<User> users = userdao.queryRaw ("where age = ?"."15"); for(User user : users) { System.out.println(user.toString()); Cursor = userdao.queryBuilder ().limit(10).orderasc (userDao.properties.age) .where(UserDao.Properties.Age.gt(15)) .buildCursor().query(); try {if(cursor ! = null) { System.out.println("-->> cursor count::" + cursor.getCount()); if (cursor.getCount() == 0) { return; } String[] columnNames = cursor.getColumnNames(); System.out.println("-->> columnNames::" + Arrays.toString(columnNames)); StringBuilder sb = new StringBuilder(); cursor.moveToFirst(); while (cursor.moveToNext()) { String firstName = cursor.getString(cursor.getColumnIndex(UserDao.Properties.FirstName.columnName)); String lastName = cursor.getString(cursor.getColumnIndex(UserDao.Properties.LastName.columnName)); String gender = cursor.getString(cursor.getColumnIndex(UserDao.Properties.Gender.columnName)); String phone = cursor.getString(cursor.getColumnIndex(UserDao.Properties.PhoneNum.columnName)); int age = cursor.getInt(cursor.getColumnIndex(UserDao.Properties.Age.columnName)); sb.append("\n{\nfirstName=").append(firstName).append(",\n") .append("lastName=").append(lastName).append(", \n") .append("gender=").append(gender).append(", \n") .append("phone=").append(phone).append(", \n") .append("age=").append(age).append(", \n") .append("}"); } System.out.println(sb.toString()); } } finally { if(cursor ! = null) cursor.close(); } // Count the number of items under the corresponding conditions. If you need to query the number without extracting the data, use this method, otherwise the performance waste is obvious. /* long totalCount = userDao.queryBuilder() .limit(10) .orderAsc(UserDao.Properties.Age) .where(UserDao.Properties.Age.gt(15)) .buildCount() .count(); System.out.println("-->>Total Count::"+ totalCount); * /}Copy the code
- use
Relational database
Relational databases almost cover most of our actual use scenarios, such as real-time communication scenarios, shopping malls, and so on. Let’s take a blog system database model as an example to familiarize ourselves with how to model these scenarios using greenDao.
-
The composite scenario
- If we have a blog, we need to associate a number of comments, and we need to know who wrote it, so we need to associate a user (publisher); So for comments, we also need to know who made the comment, so we also need to associate each comment with a user; If we also need users to be able to comment on user comments, then we also need to associate several user comment response comments with user comments; In this case, there are two kinds of relationships in this model:
- One-to-one relationship: for example, the relationship between blog and publisher, one blog for one publisher.
- One-to-many association: for example, the relationship between blog and comment here, one blog corresponds to several comments.
- If we have a blog, we need to associate a number of comments, and we need to know who wrote it, so we need to associate a user (publisher); So for comments, we also need to know who made the comment, so we also need to associate each comment with a user; If we also need users to be able to comment on user comments, then we also need to associate several user comment response comments with user comments; In this case, there are two kinds of relationships in this model:
-
Based on this relatively complex application scenario, the database model can be established as follows:
- blog
@Entity public class Blog { @Id(autoincrement = true) @Unique private long id; @NotNull private String title; private String content; @NotNull private Date createTime; @notnull private long userId; @notnull private long userId; @ToOne(joinProperty ="userId") private User user; @notnull private long commentId; // JOIN Comment @notnull private long commentId; @referencedJoinProperty = // referencedJoinProperty ="commentId"@tomany (joinProperties = {@joinProperty (name =)) // 2. You can have multiple complex joins, or you want to specify the column name of the joined column @tomany (joinProperties = {@joinProperty (name =))"commentId", referencedName = "id")}) @OrderBy("createTime ASC") List<Comment> comments; } Copy the code
- comments
- Used to comment on blogs
@Entity public class Comment { @Id(autoincrement = true) private long id; @NotNull private String title; private String content; @NotNull private Date createTime; Private long userId; private long userId; private long userId; @ToOne(joinProperty ="userId") private User user; // comment // JOIN commentSubId column private long commentSubId; @ToMany( joinProperties = {@JoinProperty( name ="commentSubId" ,referencedName = "id")}) @OrderBy("createTime ASC") List<CommentReply> subComments; } Copy the code
- Comments in response to comments
- One user posts a comment on a blog, and other users comment on that comment
@Entity public class CommentReply { @Id(autoincrement = true) private long id; @NotNull @Unique private long commentSubId; @NotNull private String title; private String content; @NotNull private Date createTime; Private long userId; private long userId; private long userId; @ToOne(joinProperty ="userId") private User user; } Copy the code
-
So how do you manipulate this relational database model? You can refer to the following sample code.
- Notice that my code is just for demonstration purposes, mainly to illustrate how to use it
GreenDao
Establish data association, practical application please think twice, otherwise the problem can not blame me ha.
- Notice that my code is just for demonstration purposes, mainly to illustrate how to use it
@Test
public void multiRelative() {
UserDao userDao = App.getDaoSession().getUserDao();
BlogDao blogDao = App.getDaoSession().getBlogDao(); CommentDao commentDao = App.getDaoSession().getCommentDao(); CommentReplyDao commentReplyDao = App.getDaoSession().getCommentReplyDao(); Publisher = new User(); publisher.setAge(24) .setGender("Male")
.setFirstName("horseLai")
.setLastName("horseLai")
.setPhoneNum("22132323323"); userDao.insertOrReplace(publisher); B / / bloglog blog = new Blog(a); blog.setTitle("GreenDao builds a relational database model");
blog.setContent("xxxxxxxxx"); blog.setCreateTime(Calendar.getInstance().getTime()); blog.setUser(publisher); // Associate with the publisher blogdao.insertorReplace (blog); // add a comment // Commenter User commentUser = new User().setphonenum ()"1234555")
.setAge(24)
.setFirstName("horseLai"); userDao.insertOrReplace(commentUser); // Comment Comment = new Comment(); comment.setTitle("Comment");
comment.setContent("Comment content"); comment.setUser(commentUser); Comment.setcreatetime (calendar.getinstance ().getTime())); commentDao.insertOrReplace(comment); User commentReplyUser = new User().setphonenum ()"12345568875")
.setAge(23)
.setFirstName("horseLai"); userDao.insertOrReplace(commentReplyUser); CommentReply = new CommentReply(); commentReply.setTitle("Reply to comments");
commentReply.setContent("Comment reply content");
commentReply.setUser(commentReplyUser);
commentReply.setCreateTime(Calendar.getInstance().getTime());
commentReplyDao.insertOrReplace(commentReply);
}
Copy the code
- To find the data
- Add and delete the search and the previous explained content is consistent, here is only a simple search, the following example code:
@Test public void query() { BlogDao blogDao = App.getDaoSession().getBlogDao(); List<Blog> blogs = blogDao.queryBuilder() .build() .list(); blogs.forEach((blog -> { System.out.println(); System.out.println(blog.toString()); System.out.println(); })); } Copy the code
- The data results are as follows:
- It can be seen that the whole model is a relationship structure similar to a tree.
Blog{ id=0, title='GreenDao builds relational database models', content='xxxxxxxxx', createTime=Tue Oct 02 14:03:27 GMT 2018, userId=1, user=User{id=1, phoneNum='22132323323', firstName='horseLai', gender='male', lastName='horseLai', age=24}, commentId=0, comments=[ Comment{ id=0, title='comments', content='Comment content', createTime=Tue Oct 02 14:03:27 GMT 2018, userId=2, user=User{ id=2, phoneNum='1234555', firstName='horseLai', gender='null', lastName='null', age=24 }, subComments=[ CommentReply{ id=0, commentSubId=0, title='Reply to comment', content='Comment reply content', createTime=Tue Oct 02 14:03:27 GMT 2018, userId=3, user=User{ id=3, phoneNum='12345568875', firstName='horseLai', gender='null', lastName='null', age=23 } } ] } ] } Copy the code