美文网首页Android
Jetpack -room (一)基本使用

Jetpack -room (一)基本使用

作者: Active_Loser | 来源:发表于2019-06-23 19:43 被阅读0次

    总结:个人见解,使用了一段时间,对于本地频繁操作数据库切数据结构复杂的应用来说,Room并不是很灵活,且需要有一定的SQL编写能力。

    一、简介

    Room是安卓中SQLite上的一个抽象层应用框架,可以更轻松、更好地保存数据。
    我们目前较多使用的是Greendao(GreenDao3.0数据库的简单使用),我们对比执行SQL的效率以及对数据库的访问,可以考虑使用Room了。


    Room的不同组件之间的这种关系如图:
    取自developer.android.google.cn

    注解:
    Entity

    @Entity:注解标识创建表,使用@Entity(tableName = "users")自定义表名
    @ColumnInfo:注解标识数据库列,使用@ColumnInfo(name = "last_name")自定义列名
    @Ignore:注解表示忽略此对象,数据库中不会创建此列;若使用继承,忽略父类的一个对象,使用@Entity(ignoredColumns = "picture")
    @NonNull:非空
    @PrimaryKey:注解表示为主键,使用@Entity(primaryKeys = {"firstName", "lastName"})表示复合主键,使用@PrimaryKey(autoGenerate = true)设置主键自且类型为INTEGER
    indices: 对特定的field建立索引加速数据库访问,索引:@Entity(indices = @Index("name")) ,复合索引:@Entity(indices = @Index(value = {"last_name", "address"}))
    @ForeignKey用于设置外键@Entity(foreignKeys = @ForeignKey(entity = User.class, parentColumns = "id",childColumns = "user_id"))

    @Dao

    @Dao:注解是一个数据访问对象
    @Insert:注解插入

    //onConflict = OnConflictStrategy.REPLACE 存在会替换
    @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);
    

    @Update注解更新

    //返回类型为int的情况,表示更新对象的个数
    @Update
    public void updateUsers(User... users);
    

    @Delete:注解为删除
    注意:使用条件删除,不能通过@Delete去做,可以使用@Query('sql')去执行。

    //返回类型为int的情况,表示删除对象的个数
    @Delete
    public void deleteUsers(User... users);
    
    

    @Query:注解为查询

    @Query("SELECT * FROM user")
     public User[] loadAllUsers();
    
    @Query("SELECT * FROM user WHERE age > :minAge")
     public User[] loadAllUsersOlderThan(int minAge);
    
     @Query("SELECT first_name, last_name FROM user WHERE region IN (:regions)")
     public List<NameTuple> loadUsersFromRegions(List<String> regions);
    
    //多表查询
     @Query("SELECT * FROM book " +
               "INNER JOIN loan ON loan.book_id = book.id " +
               "INNER JOIN user ON user.id = loan.user_id " +
               "WHERE user.name LIKE :userName")
       public List<Book> findBooksBorrowedByNameSync(String userName);
    

    二、实战

    这部分针对数据的增删改查,以及数据库升级、迁移、与Rxjava的结合使用做介绍

    2.1、基本使用

    添加依赖

    implementation 'androidx.room:room-runtime:2.1.0'
    annotationProcessor 'androidx.room:room-compiler:2.1.0'
    

    (1)创建表实体

    public class User {
        @PrimaryKey(autoGenerate = true)
        public int uid;
    
        @ColumnInfo(name = "first_name")
        public String firstName;
    
        @ColumnInfo(name = "last_name")
        public String lastName;
    }
    

    (2)创建Dao(SQ语法我们还是要学习的)

    @Dao
    public interface UserDao {
        @Query("SELECT * FROM user")
        List<User> getAll();
    
        @Query("SELECT * FROM user WHERE uid IN (:userIds)")
        List<User> loadAllByIds(int[] userIds);
    
        @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
                "last_name LIKE :last LIMIT 1")
        User findByName(String first, String last);
    
        @Insert
        void insertAll(User... users);
    
        @Delete
        void delete(User user);
    }
    

    (3)AppDatabase 使用单例,减少开销

    @Database(entities = {User.class}, version = 1,exportSchema = false)
    public abstract class AppDatabase extends RoomDatabase {
        //volatile防止重排序
        private static volatile AppDatabase mAppDatabase;
    
        public abstract UserDao userDao();
    
        public static AppDatabase getSingleton(Context context) {
            if (mAppDatabase == null) {
                synchronized (AppDatabase.class) {
                    if (mAppDatabase == null) {
                        //主线程使用.allowMainThreadQueries().build();创建
                        mAppDatabase = Room.databaseBuilder(context.getApplicationContext(), AppDatabase.class, "user.db")
                                .allowMainThreadQueries()
                                .build();
    
                    }
                }
            }
            return mAppDatabase;
        }
    }
    

    (4)使用

    AppDatabase appDatabase = AppDatabase.getSingleton(this);
    User user = new User(0,"张","三");
    User user1 = new User(1,"李","四");
    appDatabase.userDao().insertAll(user);
    appDatabase.userDao().insertAll(user1);
    List<User> userList = appDatabase.userDao().getAll();
    

    2.2 类型转换器

    定义类型转换器

    public class Converters {
        @TypeConverter
        public static Date fromTimestamp(Long value) {
            return value == null ? null : new Date(value);
        }
    
        @TypeConverter
        public static Long dateToTimestamp(Date date) {
            return date == null ? null : date.getTime();
        }
    }
    

    使用类型转换器

    (1) 放在Database,那么该数据库中的所有Daos和Entities都可以使用它。
    (2) 放在Dao,Dao中的所有方法都可以使用它。
    (3) 放在Entity,实体的所有字段都可以使用它。
    (4) 放在Entity字段上,则只有该字段才能使用它。
    (5) 放在Dao方法上,该方法的所有参数都可以使用它。

    //放在Dao方法参数上,那么只有该字段才能使用它。
    @TypeConverters({Converters.class})
    

    2.3 与RxJava并肩作战

    添加依赖

    implementation 'androidx.room:room-rxjava2:2.1.0-beta01'
    

    @Query方法:房间支持类型的返回值 Publisher, Flowable和 Observable`。

    @Insert@Update@Delete方法:2.1.0室和更高版本支持返回类型的值 CompletableSingle<T>Maybe<T>

    @Dao
    public interface MyDao {
        @Query("SELECT * from user where id = :id LIMIT 1")
        public Flowable<User> loadUserById(int id);
    
        // Emits the number of users added to the database.
        @Insert
        public Maybe<Integer> insertLargeNumberOfUsers(List<User> users);
    
        // Makes sure that the operation finishes successfully.
        @Insert
        public Completable insertLargeNumberOfUsers(User... users);
    
        /* Emits the number of users removed from the database. Always emits at
           least one user. */
        @Delete
        public Single<Integer> deleteUsers(List<User> users);
    }
    

    2.4 数据库升级

    要使迁移逻辑按预期运行,使用完整查询,而不是引用表示查询的常量,否则会造成数据丢失

    static final Migration MIGRATION_1_2 = new Migration(1, 2) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("CREATE TABLE `Fruit` (`id` INTEGER, "
                    + "`name` TEXT, PRIMARY KEY(`id`))");
        }
    };
    
    static final Migration MIGRATION_2_3 = new Migration(2, 3) {
        @Override
        public void migrate(SupportSQLiteDatabase database) {
            database.execSQL("ALTER TABLE Book "
                    + " ADD COLUMN pub_year INTEGER");
        }
    };
    
    Room.databaseBuilder(getApplicationContext(), MyDb.class, "database-name")
            .addMigrations(MIGRATION_1_2, MIGRATION_2_3).build();
    

    相关文章

      网友评论

        本文标题:Jetpack -room (一)基本使用

        本文链接:https://www.haomeiwen.com/subject/vjmiqctx.html