Android Room 基本应用笔记

Android Room 笔记

导入

app.build.gradle中的dependecies{}代码块内添加如下引用

    def room_version = "2.2.3"

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

    // optional - RxJava support for Room
    implementation "androidx.room:room-rxjava2:$room_version"

建库

创建继承自androidx.room.RoomDatabase的抽象类,并为该类添加注解,如下所示


@Database(entities = {User.class, Login.class}, version = 1)
public abstract class DatabaseName extends RoomDatabase {
    ...
}
@Database(entities = arrayOf(User::class, Login::class), version = 1)
abstract class DatabaseName: RoomDatabase() {
    ...
}

该例子建立了一个拥有User、Login两张表的版本为1的数据库

之后对数据库进行初始化(建议在Application中进行)

初始化示例如下


void initDB(Context ctx, String dbName){
    DatabaseName db = Room.databaseBuilder(ctx.getApplicationContext(), DatabaseName.class, dbName).build();
}
fun initDB(ctx: Context, dbName: String){
    val db = Room.databaseBuilder(ctx.applicationContext, DatabaseName::class.java, dbName).build()
}

获取到DatabaseName实例后,建议确保其为单例模式使用,因为每次获取的开销都不小

使用@Database的类应满足以下条件

  • 继承自RoomDatabase的抽象类
  • 在注释中添加与数据库关联的实体列表
  • 包含无参且返回通过@Dao注释的类的抽象方法(在建表部分详细解释)

建表

@Entity

通过由@Entity注解修饰的Java Bean类来构建,请确保各个属性对Room来说都是可见的

基本用法
@Entity
public class User {
    @PrimaryKey
    public long uid;
    
    @ColumnInfo(name = "first_name")
    public String firstName;
    
    @ColumnInfo(name = "last_name")
    public String lastName;
}
@Entity
data class User(
    @PrimaryKey val uid: Int,
    @ColumnInfo(name = "first_name") val firstName: String?,
    @ColumnInfo(name = "last_name") val lastName: String?
)

如上创建了一个User表,包含一个主键uid和两个字段。

自增主键

通过@PrimaryKey修饰的字段会被当成主键。若需要该主键自动生成,可以使用如下写法

@PrimaryKey(autoGenerate = true)
public long uid;
复合主键

每个实体必须至少有一个字段为主键。通过@Entity(primaryKeys = [])来进行配置,此时请不要使用@PrimaryKey修饰其它字段,并确保主键均为NonNull类型

@Entity(primaryKeys = {"firstName", "lastName"})
public class User {
    @NonNull
    public String firstName;
    @NonNull
    public String lastName;
}
  @Entity(primaryKeys = arrayOf("firstName", "lastName"))
    data class User(
        val firstName: String,
        val lastName: String
    )
定义字段名

默认下,数据库将用类名作为表名。若希望规定不同名称,可以使用@EntitytableName属性(数据库名称不区分大小写)

@Entity(tableName = "users")
public class User {
    ...
}
@Entity(tableName = "users")
data class User (
     ...
)

同样的,可以用@ColumnInfoname属性定义字段名

忽略字段

Room会为实体的每一个字段创建一个类。如果有些字段并非用来建表,可以使用@Ignore为其进行注释

若其存在继承关系,则建议使用@EntityignoredColumns进行注释

官方的示例如下

@Entity(ignoredColumns = "picture")
public class RemoteUser extends User {
    @PrimaryKey
    public int id;

    public boolean hasVpn;
}
open class User {
    var picture: Bitmap? = null
}

@Entity(ignoredColumns = arrayOf("picture"))
data class RemoteUser(
    @PrimaryKey val id: Int,
    val hasVpn: Boolean
) : User()
字段唯一

部分数据库中的字段或字段组内容必须唯一,可以用@Indexunique属性进行设置。当尝试插入重复字段时会抛出RuntimeException

    @Entity(indices = {@Index(value = {"first_name", "last_name"},
            unique = true)})
    public class User {
        @PrimaryKey
        public int id;

        @ColumnInfo(name = "first_name")
        public String firstName;

        @ColumnInfo(name = "last_name")
        public String lastName;

        @Ignore
        Bitmap picture;
    }
    @Entity(indices = arrayOf(Index(value = ["first_name", "last_name"],
            unique = true)))
    data class User(
        @PrimaryKey val id: Int,
        @ColumnInfo(name = "first_name") val firstName: String?,
        @ColumnInfo(name = "last_name") val lastName: String?,
        @Ignore var picture: Bitmap?
    )

@Dao

使用@Dao修饰的接口类来确定业务接口。该接口最后会通过生成Room.databaseBuilder时实现其前文提到的无参抽象方法来获取。

官方示例非常清晰

 @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);
    }
    @Dao
    interface UserDao {
        @Query("SELECT * FROM user")
        fun getAll(): List<User>

        @Query("SELECT * FROM user WHERE uid IN (:userIds)")
        fun loadAllByIds(userIds: IntArray): List<User>

        @Query("SELECT * FROM user WHERE first_name LIKE :first AND " +
               "last_name LIKE :last LIMIT 1")
        fun findByName(first: String, last: String): User

        @Insert
        fun insertAll(vararg users: User)

        @Delete
        fun delete(user: User)
    }

记得在之前编写的DatabaseName.class中添加获取该类实例的抽象方法

@Database(entities = {User.class, Login.class}, version = 1)
public abstract class DatabaseName extends RoomDatabase {
    public abstract UserDao getUserDao();
}
@Database(entities = {User.class, Login.class}, version = 1)
public abstract class DatabaseName extends RoomDatabase {
    abstract fun userDao(): UserDao
}

在实际操作中,即可使用得到的数据库类实例来进行操作

void sampleFun(){
    DatabaseName db = Room.databaseBuilder(ctx.getApplicationContext(), DatabaseName.class, dbName).build();
    
    //查询所有用户
    List<User> userList = db.getUserDao().getAll();
}
fun sampleFun(){
    val db = Room.databaseBuilder(ctx.applicationContext, DatabaseName::class.java, dbName).build()
    
    val userList = db.userDao.all
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值