天天看點

Android jetpack Room資料庫(一)基本使用

1.gradle添加引用

def room_version = "2.2.5"
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
           

2.配置編譯器選項

android {
    ...
    defaultConfig {
        ...
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [
                    "room.schemaLocation":"$projectDir/schemas".toString(),  //配置并啟用架構導出到給定目錄中【"$projectDir/schemas".toString()】的json檔案功能
                    "room.incremental":"true",  //啟用 Gradle 增量注釋處理器 
                    "room.expandProjection":"true"] //配置 Room 以重寫查詢 ,設定成false則不需要導出到指定目錄json檔案
            }
        }
    }
}
           

不配置會報如下錯誤: 警告: Schema export directory is not provided to the annotation processor so we cannot export the schema. You can either provide

room.schemaLocation

annotation processor argument OR set exportSchema to false.

3.添權重限

room資料庫需要存儲讀寫權限

<!-- 讀寫 外部存儲 權限 -->
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> 
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
           

4.建立實體類

需要在類上加上Entity注解

@Entity(tableName = "user",ignoredColumns = {"testField1"})  //實體類建立需要加上@Entity注解
public class User {
    @PrimaryKey(autoGenerate = true) //@PrimaryKey 聲明id這個字段為主鍵。autoGenerate自增
    public int id;
    @ColumnInfo(name = "user_name")//@ColumnInfo将此列名重命名為name屬性所指派的名字
    public String userName;
    @ColumnInfo(name = "user_age")
    public int userAge;
    @ColumnInfo(name = "user_mobile")
    public String userMobile;
​
    public String testField1;
    @Ignore                       //@Ignore 此屬性不在資料庫生産列
    public String testField2;
​
    public User() {
    }
​
    @Ignore  //@Ignore 有參構造方法必須加上,否則将會報錯
    public User(String userName, int userAge) {
        this.userName = userName;
        this.userAge = userAge;
    }
    @Ignore  //@Ignore 有參構造方法必須加上,否則将會報錯
    public User(String userName, int userAge, String userMobile) {
        this.userName = userName;
        this.userAge = userAge;
        this.userMobile = userMobile;
    }
​
   
}
           

5.看看Entity注解的内容

@Target(ElementType.TYPE) //定義作用域,ElementType.TYPE表示此注解可以作用在類、接口、注解和枚舉上
@Retention(RetentionPolicy.CLASS)//保留級别 RetentionPolicy.CLASS 保留到編譯期間,反射可用
public @interface Entity {
    /**
     * The table name in the SQLite database. If not set, defaults to the class name.
     *  表名,不設定此屬性的話會預設将className作為表名
     * @return The SQLite tableName of the Entity.
     */
    String tableName() default "";
​
    /**
     * List of indices on the table.
     * 表索引  預設為空數組
     * @return The list of indices on the table.
     */
    Index[] indices() default {};
​
    /**
     * 是否從父類繼承索引,如果是true,将會從其父類繼承父類所聲明的所有索引,即使父類此屬性設定為false,隻要本類設定為true,都會将父類中聲明的索引全部繼承過來。如果從父類繼承了索引,那麼從父類繼承的索引将會根據Sqlite命名規則重新命名,因為Sqlite同一個資料庫中不允許有相同的索引
     *
     預設為false
     */
    boolean inheritSuperIndices() default false;
​
    /**
     * The list of Primary Key column names.
     主鍵定義
     * <p>
     * If you would like to define an auto generated primary key, you can use {@link PrimaryKey}
     * annotation on the field with {@link PrimaryKey#autoGenerate()} set to {@code true}.
     *
     * @return The primary key of this Entity. Can be empty if the class has a field annotated
     * with {@link PrimaryKey}.
     */
    String[] primaryKeys() default {};
​
    /**
     * List of {@link ForeignKey} constraints on this entity.
     *外鍵
     * @return The list of {@link ForeignKey} constraints on this entity.
     */
    ForeignKey[] foreignKeys() default {};
​
    /**
     * The list of column names that should be ignored by Room.
     * <p> 忽略的屬性,即不在資料表中生成列的字段
     * Normally, you can use {@link Ignore}, but this is useful for ignoring fields inherited from
     * parents.
     * <p>
     * Columns that are part of an {@link Embedded} field can not be individually ignored. To ignore
     * columns from an inherited {@link Embedded} field, use the name of the field.
     *
     * @return The list of field names.
     */
    String[] ignoredColumns() default {};
}
           

6.建立接口Dao

@Dao //加上@Dao注解
public interface UserDao {
/**
*資料庫操作注解分别有: Query  Insert  Update  Delete
*
*/
    //Query的值即使要執行的sql語句
    @Query("SELECT * FROM user")
    List<User> getAll();
​
    @Query("SELECT * FROM user WHERE user_name in (:names)")
    List<User> getUsersByMames(List<String> names);
​
    //注意點: 在Room使用中,模糊比對的格式為" like '%' || :userName || '%' ",即在要比對的參數值前後要加上 “||”,并且“%”要區分出來
    @Query("SELECT * FROM user WHERE user_name like '%'|| :userName ||'%' LIMIT 1")
    User getUserInfoByName(String userName);
​
    @Insert  //Insert 可以單獨插入,也可以批量插入
    void insertUser(User user);
​
    @Insert
    void insertUsers(List<User> users);
}
           

7.建立DataBase抽象類

//建立database類繼承自RoomDatabase類,必須聲明成abstract
//entities,指定需要建立的資料表的類,必須有Entity注解,version ,指定資料庫版本
@Database(entities = {User.class}, version = 1) 
public abstract class AppDataBase extends RoomDatabase {
    
    public abstract UserDao userDao();
​
    private final static String DATABASE_NAME = "test_db";
​
    private static AppDataBase instance;
​
    public static AppDataBase getInstance(Context context) {
        if (instance == null) {
            synchronized (AppDataBase.class) {
                if (instance == null) {
                    instance = Room.databaseBuilder(context.getApplicationContext(), AppDataBase.class, DATABASE_NAME).build();
                }
            }
        }
        return instance;
    }
​
}
           

8.使用

private void createTestData() {
        new Thread() {
        //資料庫操作不能再主線程,否則會報錯
            @Override
            public void run() {
                super.run();
                User user = new User();
                user.userAge = 18;
                user.userName = "Databinding";
                user.userMobile = "15888888888";
​
            //通過query語句删除單個資料                                               AppDataBase.getInstance(MainActivity.this).userDao().delete(user.userName);
                //插入單條資料
                AppDataBase.getInstance(MainActivity.this).userDao().insertUser(user);
​
                String names[] = new String[]{"Lifecycles", "LiveData", "Navigation", "Paging", "ViewModel"};
                int[] ages = new int[]{19, 19, 18, 20, 21};
                List<User> userList = new ArrayList<>();
                for (int i = 0; i < names.length; i++) {
                    User mUser = new User(names[i], ages[i % ages.length]);
                    userList.add(mUser);
                }
                //模拟删除資料
                AppDataBase.getInstance(MainActivity.this).userDao().deletes(names);
            //模拟批量插入    AppDataBase.getInstance(MainActivity.this).userDao().insertUsers(userList);
​
            }
        }.start();
    }
           

9.下一篇預告

下一篇将會對room資料庫的更新以及複雜資料類型存儲進行記錄