preface
Android data persistence layer directly using SQLite is very troublesome, Google officially launched Room, Google’s definition of Room: The Room persistence library provides an abstraction layer over SQLite to allow fluent database access while harnessing SQLite. Room is an abstraction layer on SQLite, which is used to get rid of tedious database operations, including creating, updating databases, tables, adding, deleting, checking, etc.
Room database structure
As shown below, the Room database contains three objects:
Entity: Corresponds to a table in the database. You can use the Entity annotation to turn a class into a table structure in the database.
DAO: full name Database Access
Object defines operations such as reading and writing data in the database. DAO can use SQL statements to operate the database.
RoomDatabase: Database holding classes for creating or connecting to databases. Internal contains DAO and Entity.
Entity
An Entity in Room Database represents a data table structure, and an Entity instance is a row in the table, such as an Entity that defines a Person class.
@Entity
public class Person{
@PrimaryKey
public int id;
public String firstName;
public String lastName;
}
Copy the code
When there are two Person objects in a table, the table contains the following data:
Key points:
An Entity object represents a row in a table, and an Entity class represents a table.
Entity member variables are columns in the data table.
3, a Java class is defined as Entity by the Entity annotation.
The use of the Entity
1. Define an Entity
@Entity(tableName = "person_table")
public class Person{
@PrimaryKey
public int id;
public String firstName;
public String lastName;
}
Copy the code
If you want to name an Entity, you can add (tableName = “person_table”) to the end of the @entity annotation. If you don’t, the default name will be used. The id, firstName, and lastName are defined as public. So that the database can have permission to manipulate the data, or you can choose to set it all to private and do it through setters and getters.
2. Define primary keys
Define at least one primary key for each Entity, even if there is only one variable in the Entity. Use the @primaryKey annotation in the Room database to define the primary key. There are two ways to use @primarykey: you can add it before the class variable, or you can add it after the @entity annotation if the PrimaryKey is more complex.
@Entity(primaryKeys = {"firstName"."lastName"})
public class User {
public String firstName;
public String lastName;
}
Copy the code
3. Change the attribute column name
As with tableName, you can change column names in a table, using @columnInfo to change column names. By default, the variable name is lowercase.
@Entity(tableName = "person_table")
public class Person {
@PrimaryKey
public int id;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
Copy the code
4, some variables do not generate data table fields
If you do not want a variable to generate an attribute column in the table, you can use the @ignore annotation.
@Entity
public class Person {
@PrimaryKey
public int id;
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
Copy the code
IgnoredColumns can be used if a class inherits from the Person class above and does not want Picture to generate columns in the data table
@Entity(ignoredColumns = "picture")
public class RemotePerson extends Person {
@PrimaryKey
public int id;
public boolean hasVpn;
}
Copy the code
5. Two tables are associated
SQLite is a relational database, which can specify the relationship between two objects. Most relational databases can specify the association between tables, but Room database can not specify the relationship between two tables, but can carry out the association of tables through the @foreignKey annotation.
@Entity(foreignKeys = @ForeignKey(entity = Person.class,
parentColumns = "id",
childColumns = "user_id"))
public class Book {
@PrimaryKey
public int bookId;
public String title;
@ColumnInfo(name = "user_id")
public int userId;
}
Copy the code
6. Nested Entity
If you define an Entity class that has an object in it and you want the table column fields in the Entity class to contain variables in the Entity class object, you can add the @Embedded annotation to the Entity class object.
public class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code")
public int postCode;
}
@Entity
public class Person{
@PrimaryKey
public int id;
public String firstName;
@Embedded
public Address address;
}
Copy the code
So the column fields in the Person table have ID, firstName, street, state, city, and post_code.
DAO
In the DAO(Data Access Object), database operations can be performed using SQL statements and associated with Java method calls. The compiler checks the SQL statements and generates the corresponding query statements through annotations, such as @INSERT.
Note:
DAO must now be an abstract class or interface
2. All queries must be executed in a separate thread.
The use of DAO
You can use statements in SQL to implement DAO operations.
1. Insert data
When the @INSERT annotation is used before a method, the Room database inserts all the parameters of the method into the data table.
@Dao
public interface MyDao {
@Insert(onConflict = OnConflictStrategy.REPLACE)
public void insertUsers(User... users);
@Insert
public void insertBothUsers(User user1, User user2);
@Insert
public void insertUsersAndFriends(User user, List<User> friends);
}
Copy the code
When the @INSERT method inserts only one parameter, the Insert returns long data representing the row number of the inserted object in the table. When an array or collection is inserted, the long array or collection is returned. 2. Update data
The @update annotation method looks for the same data in the table as the given data primary key and updates it.
@Dao
public interface MyDao {
@Update
public void updateUsers(User... users);
}
Copy the code
3. Query data
The @query annotated Query method is the most used method, and each Query method is validated at compile time. If it fails, an error is reported, and no further failure is reported at runtime. in
@Dao
public interface MyDao {
@Query("SELECT * FROM user")
public User[] loadAllUsers();
}
Copy the code
If there is a query syntax error, or if the user table does not exist in the database, the Room database will display an error message at compile time. Complex queries can also be implemented using SQL statements
@Dao
public interface MyDao {
@Query("SELECT * FROM user WHERE age BETWEEN :minAge AND :maxAge")
public User[] loadAllUsersBetweenAges(int minAge, int maxAge);
@Query("SELECT * FROM user WHERE first_name LIKE :search " +
"OR last_name LIKE :search")
public List<User> findUserWithName(String search);
}
Copy the code
Query the data in the list and return the sublist
Sometimes it is not necessary to return all fields of the query data; most of the time it is only necessary to return a subfield of the query data. The following implementation returns a subdomain of the query.
public class NameTuple {
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
Copy the code
The query then returns the fields in the subdomain
@Dao
public interface MyDao {
@Query("SELECT first_name, last_name FROM user")
public List<NameTuple> loadFullName(a);
}
Copy the code
RoomDatabase
Entity defines a table. The DAO defines operations on the data in the table. RoomDatabase contains the DAO and provides methods for creating and connecting to the database.
Create Room database
Creating a RoomDatabase involves three steps: 1. Create an abstract class that inherits from RoomDatabase.
2. Use the @database annotation before inherited classes.
Declare the Entity of the database structure and set the version number of the database.
@Database(entities = {Word.class}, version = 1)// Declare the version number of Entity and database
public abstract class WordRoomDatabase
extends RoomDatabase {
public abstract WordDao wordDao(a);// Create an abstract class for DAO
private static WordRoomDatabase INSTANCE;// Create a singleton
static WordRoomDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
synchronized (WordRoomDatabase.class) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(
context.getApplicationContext(),
WordRoomDatabase.class, "word_database") .addCallback(sOnOpenCallback) .fallbackToDestructiveMigration() .build(); }}}returnINSTANCE; }private static RoomDatabase.Callback sOnOpenCallback =
new RoomDatabase.Callback(){
@Override
public void onOpen (@NonNull SupportSQLiteDatabase db){
super.onOpen(db);
initializeData();
}};
}
Copy the code
Note: 1. Check whether the SQL statement is correct during compilation
2. Do not perform database operations on the main thread
3. RoomDatabase is best used in singleton mode
Finally, Android interacts with the Room database while using the Room database
Room database Migration
When upgrading an Android application, it is sometimes necessary to change the structure of the data in the database to keep the original data unchanged when users upgrade the application. Migration using the database is necessary. The Room Persistence Library library in the Room database provides a way to save user data when upgrading the database. Methods are used to define Migration objects, each containing the start and end version numbers of the database.
static final Migration MIGRATION_1_2 = new Migration(1.2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
// Change the structure of the table}};Copy the code
Implement the Migration object above and override the Migrate method to implement the upgrade operations in the Migrate method.
static final Migration MIGRATION_2_3 = new Migration(2.3) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE users "
+ " ADD COLUMN last_update INTEGER"); }};Copy the code
If we were to upgrade our database from version 1 to version base, we would define MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4 and rewrite the singleton methods.
public static UsersDatabase getInstance(Context context) {
synchronized (sLock) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
UsersDatabase.class, "Sample.db")
.addMigrations(MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4)
.build();
}
returnINSTANCE; }}Copy the code
MIGRATION_1_2, MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4, MIGRATION_1_4, MIGRATION_1_4, MIGRATION_1_4, MIGRATION_1_4, MIGRATION_1_4 However, if sufficient MIGRATION is not provided and the Room database changes from the current version to the latest version, the original data will be overwritten.
reference
1, developer.android.com/training/da…
2, codelabs.developers.google.com/codelabs/an…
My CSDN
Blog.csdn.net/u013309870/…