前言
Android中提供了SQLite数据库进行数据的持久化 ,并提供了对应API访问数据库,而Room框架提供了SQLite数据访问抽象层,为高效的数据库访问层带来便捷
APP可以缓存用户数据,当APP离线时便从SQLite读取数据,当重新连线时即可完成和服务器数据的同步
谷歌官方强烈推荐使用Room框架操作SQLite数据库
Hello World
首先在build.gradle
中添加必要依赖
dependencies {
def room_version = "1.1.1"
implementation "android.arch.persistence.room:runtime:$room_version"
annotationProcessor "android.arch.persistence.room:compiler:$room_version" // use kapt for Kotlin
// optional - RxJava support for Room
implementation "android.arch.persistence.room:rxjava2:$room_version"
// optional - Guava support for Room, including Optional and ListenableFuture
implementation "android.arch.persistence.room:guava:$room_version"
// Test helpers
testImplementation "android.arch.persistence.room:testing:$room_version"
}
创建实体类User
,@Entity
表示该类对应数据库中的表,@ColumnInfo
后面的name
属性对应数据库中的字段名,并实现该实体类的Getter
,Setter
方法
@Entity
public class User {
@PrimaryKey
private int uid;
@ColumnInfo(name = "first_name")
private String firstName;
@ColumnInfo(name = "last_name")
private String lastName;
public int getUid() {
return uid;
}
public void setUid(int uid) {
this.uid = uid;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public String toString() {
return "User{" +
"uid=" + uid +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
'}';
}
}
创建实体类对应的dao
层UserDao
,完成User的增删改查(CRUD
)接口定义,@Dao
注解定义一个dao层,参数赋值(传递)使用:clumn_name
进行赋值
@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(onConflict = OnConflictStrategy.REPLACE)
void insertAll(User... users);
@Delete
void delete(User user);
}
创建AppDatabase
,@Database
注解表示这是一个数据库操作类,entities
对应Entity
实体类,version
用于数据库版本升级,并在该抽象类中定义一个返回dao
层的抽象方法
@Database(entities = {User.class}, version = 1, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
初始化用于操作数据库的实例对象AppDatabase
,需要注意的是不能在主线程中初始化,必须新开启一个线程进行初始化,否则会报错,或者无法创建数据库
new Thread(new Runnable() {
@Override
public void run() {
AppDatabase db = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, "database-name").build();
}
}).start();
测试
增加,也可以传一个User
数组
for (int i = 0; i < 10; i++) {
User user = new User();
user.setUid(i);
user.setFirstName("Shell" + i);
user.setLastName("Hub" + i);
insertAll(db, user);
}
如果报以下错误,修改dao层的注解为@Insert(onConflict = OnConflictStrategy.REPLACE)
android.database.sqlite.SQLiteConstraintException: UNIQUE constraint failed: User.uid (code 1555 SQLITE_CONSTRAINT_PRIMARYKEY)
查询所有数据
for (User user : db.userDao().getAll()) {
System.out.println(user);
}
other...
Room单例模式
最好使用设计模式中的单例模式获取数据库实例,因为每次获取数据库实例都很耗时并且耗内存,我们可以自定义一个类继承Application
并定义一个public static
方法获取数据库实例
public class App extends Application {
private static Context context;
private static final String DATABASE_NAME = "SHELLHUB";
private static AppDatabase DB_INSTANCE;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
new Thread(new Runnable() {
@Override
public void run() {
DB_INSTANCE = Room.databaseBuilder(getApplicationContext(),
AppDatabase.class, DATABASE_NAME).build();
}
}).start();
}
public static AppDatabase getDB() {
return DB_INSTANCE;
}
}