概述
Room持久性庫(kù)在SQLite的基礎(chǔ)上提供了一個(gè)抽象層炼列,讓用戶能夠在充分利用SQLite的強(qiáng)大功能的同時(shí)眠蚂,獲享更強(qiáng)健的數(shù)據(jù)庫(kù)訪問(wèn)機(jī)制辐董。
添加依賴
在app的build.gradle中添加如下依賴:
def room_version ="2.2.6"
implementation"androidx.room:room-runtime:$room_version"
annotationProcessor"androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// Test helpers
testImplementation"androidx.room:room-testing:$room_version"
在app的build.gradle文件中甚亭,配置schemaLocation選項(xiàng)為app/schemas伐坏,方便我們查看數(shù)據(jù)庫(kù)架構(gòu)信息怔匣。
defaultConfig{
...
//指定room.schemaLocation生成的文件路徑
javaCompileOptions{
annotationProcessorOptions{
arguments =["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
}
等我們創(chuàng)建好表和數(shù)據(jù)庫(kù)等信息的時(shí)候,編譯一下桦沉,會(huì)在app/schemas目錄下生成這樣的Json文件每瞒。
創(chuàng)建一個(gè)實(shí)體類(lèi),對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表
@Entity(tableName ="User" ,indices ={@Index(value ={"user_name"}, unique =true)})//數(shù)據(jù)庫(kù)實(shí)體
public class User {
@PrimaryKey(autoGenerate =true)
private long id;
@ColumnInfo(name ="user_name")
private String name;
@ColumnInfo(name ="user_gender")
private String gender;
private int age;
private int type;
public User() {
}
public User(long id,String name,String gender,int age,int type) {
this.id = id;
this.name = name;
this.gender = gender;
this.age = age;
this.type = type;
}
public User(String name,String gender,int age,int type) {
this.name = name;
this.gender = gender;
this.age = age;
this.type = type;
}
@Entity:注解的類(lèi)對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表纯露,我們可以指定表名剿骨,如果不指定的話,默認(rèn)是類(lèi)的名字埠褪。
@PrimaryKey:每一個(gè)表都需要一個(gè)主鍵浓利,這點(diǎn)需要注意,Room就是根據(jù)主鍵是否相同來(lái)判斷是否是同一個(gè)對(duì)象钞速。
@ColumnInfo:指定類(lèi)的屬性在表中列的名字贷掖,如果不指定,默認(rèn)就是屬性名渴语。
注意苹威,存儲(chǔ)在數(shù)據(jù)庫(kù)中的類(lèi)屬性可見(jiàn)性必須是public的。
創(chuàng)建DAO(data access object)
DAO必須是接口或者抽象類(lèi)驾凶,Room使用注解幫我們生成訪問(wèn)數(shù)據(jù)庫(kù)的代碼牙甫,感覺(jué)和Retrofit有類(lèi)似之處。接下來(lái)我們創(chuàng)建一個(gè)DAO類(lèi)调违,具有簡(jiǎn)單的增刪改查的功能窟哺。
@Dao //Database access object 數(shù)據(jù)庫(kù)訪問(wèn)接口 所有增刪改查等操作都在此聲明
public interface UserDao {
// long 表示插入數(shù)據(jù)后返回的id
@Insert(onConflict =OnConflictStrategy.REPLACE)
void insertUser(User... user);
// int 影響的行數(shù)
@Update
int updateUser(User... user);
@Delete
int deleteUser(User... user);
@Query("DELETE FROM USER")
void deleteUser();
@Query("SELECT * FROM USER ORDER BY ID DESC")
List<User> getAllUser();
@Query("SELECT * FROM USER ORDER BY ID DESC")
LiveData<List<User>> getAllUserLive();
}
添加Room數(shù)據(jù)庫(kù)
//exportSchema = false 是不會(huì)導(dǎo)出 schemas json 結(jié)構(gòu)
@Database(entities ={User.class}, version =2, exportSchema =true)
public abstract class UserDatabase extends RoomDatabase {
public abstract UserDao getUserDao();
private static UserDatabase userDatabase;
synchronized public static UserDatabase getUserDatabase(Context context) {
if (null ==userDatabase) {
userDatabase =Room.databaseBuilder(context.getApplicationContext(),UserDatabase.class,"android_room_dev.db")
.allowMainThreadQueries()
.addMigrations(migration) //保留原有數(shù)據(jù)
.build();
}
return userDatabase;
}
static final Migration migration =new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE user ADD COLUMN type INTEGER NOT NULL DEFAULT 1");
//sqlLet沒(méi)有刪除字段語(yǔ)句,只能創(chuàng)建新的數(shù)據(jù)庫(kù)定義需要的字段翰萨,將原有數(shù)據(jù)庫(kù)數(shù)據(jù)復(fù)制過(guò)去脏答,刪除舊數(shù)據(jù)庫(kù)后再將新數(shù)據(jù)庫(kù)重命名
}
};
}
Room數(shù)據(jù)庫(kù)必須是一個(gè)繼承自RoomDatabase的抽象類(lèi)。通常情況下應(yīng)用內(nèi)應(yīng)該只有一個(gè)Room數(shù)據(jù)庫(kù)實(shí)例亩鬼。
在demo中的簡(jiǎn)單使用
public class MainActivity extends AppCompatActivity {
TextView tvAdd;
TextView tvUpdate;
TextView tvDelete;
TextView tvQuery;
TextView tvQueryAll;
TextView tvContent;
UserDatabase userDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
userDatabase =UserDatabase.getUserDatabase(this);
setContentView(R.layout.activity_main);
tvAdd = findViewById(R.id.tv_add);
tvUpdate = findViewById(R.id.tv_update);
tvDelete = findViewById(R.id.tv_delete);
tvQuery = findViewById(R.id.tv_query);
tvQueryAll = findViewById(R.id.tv_queryAll);
tvContent = findViewById(R.id.tv_content);
UserDao userDao =userDatabase.getUserDao();
LiveData<List<User>> listLiveData =userDao.getAllUserLive();
listLiveData.observe(this,new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
String s ="";
for (int i =0; i < users.size(); i++) {
User user = users.get(i);
s +="姓名:" +user.getName() +"性別:" +user.getGender() +"年齡:" +user.getAge() +"類(lèi)型:" +user.getType() +"\n";
}
tvContent.setText(s);
}
});
tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
User user =new User();
user.setName("張三" +new Random().nextInt(100));
user.setAge(new Random().nextInt(100));
user.setGender(new Random().nextInt(1) +"");
user.setType(new Random().nextInt(9));
userDao.insertUser(user);
}
});
tvUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
User user =users.get(0);
user.setName("瑪麗哈利");
userDao.updateUser(user);
}
});
tvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
if(users!=null &&users.size()>0){
User user =users.get(0);
userDao.deleteUser(user);
}
}
});
tvQuery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
String s ="";
for (int i =0; I
User user =users.get(i);
s +="姓名:" +user.getName() +"性別:" +user.getGender() +"年齡:" +user.getAge() +"類(lèi)型:" +user.getType() +"\n";
}
Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
}
});
tvQueryAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
}
```**概述**
Room持久性庫(kù)在SQLite的基礎(chǔ)上提供了一個(gè)抽象層殖告,讓用戶能夠在充分利用SQLite的強(qiáng)大功能的同時(shí),獲享更強(qiáng)健的數(shù)據(jù)庫(kù)訪問(wèn)機(jī)制雳锋。
**添加依賴**
在app的build.gradle中添加如下依賴:
def room_version ="2.2.6"
implementation"androidx.room:room-runtime:$room_version"
annotationProcessor"androidx.room:room-compiler:$room_version" // For Kotlin use kapt instead of annotationProcessor
// Test helpers
testImplementation"androidx.room:room-testing:$room_version"
**在app的build.gradle文件中黄绩,配置schemaLocation選項(xiàng)為app/schemas,方便我們查看數(shù)據(jù)庫(kù)架構(gòu)信息玷过。**
defaultConfig{
...
//指定room.schemaLocation生成的文件路徑
javaCompileOptions{
annotationProcessorOptions{
arguments =["room.schemaLocation":"$projectDir/schemas".toString()]
}
}
}
等我們創(chuàng)建好表和數(shù)據(jù)庫(kù)等信息的時(shí)候爽丹,編譯一下,會(huì)在app/schemas目錄下生成這樣的Json文件辛蚊。
【 ! + [圖片名稱] + (https://upload-images.jianshu.io/upload_images/7182690-7cae1e445eb5801c.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1200) 】
**創(chuàng)建一個(gè)實(shí)體類(lèi)粤蝎,對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表**
@Entity(tableName ="User" ,indices ={@Index(value ={"user_name"}, unique =true)})//數(shù)據(jù)庫(kù)實(shí)體
public class User {
@PrimaryKey(autoGenerate =true)
private long id;
@ColumnInfo(name ="user_name")
private String name;
@ColumnInfo(name ="user_gender")
private String gender;
private int age;
private int type;
public User() {
}
public User(long id,String name,String gender,int age,int type) {
this.id = id;
this.name = name;
this.gender = gender;
this.age = age;
this.type = type;
}
public User(String name,String gender,int age,int type) {
this.name = name;
this.gender = gender;
this.age = age;
this.type = type;
}
+ @Entity:注解的類(lèi)對(duì)應(yīng)數(shù)據(jù)庫(kù)中的一張表,我們可以指定表名袋马,如果不指定的話初澎,默認(rèn)是類(lèi)的名字。
+ @PrimaryKey:每一個(gè)表都需要一個(gè)主鍵虑凛,這點(diǎn)需要注意碑宴,Room就是根據(jù)主鍵是否相同來(lái)判斷是否是同一個(gè)對(duì)象。
+ @ColumnInfo:指定類(lèi)的屬性在表中列的名字桑谍,如果不指定延柠,默認(rèn)就是屬性名。
+ 注意锣披,存儲(chǔ)在數(shù)據(jù)庫(kù)中的類(lèi)屬性可見(jiàn)性必須是public的贞间。
**創(chuàng)建DAO(data access object)**
DAO必須是接口或者抽象類(lèi),Room使用注解幫我們生成訪問(wèn)數(shù)據(jù)庫(kù)的代碼雹仿,感覺(jué)和Retrofit有類(lèi)似之處榜跌。接下來(lái)我們創(chuàng)建一個(gè)DAO類(lèi),具有簡(jiǎn)單的增刪改查的功能盅粪。
@Dao //Database access object 數(shù)據(jù)庫(kù)訪問(wèn)接口 所有增刪改查等操作都在此聲明
public interface UserDao {
// long 表示插入數(shù)據(jù)后返回的id
@Insert(onConflict =OnConflictStrategy.REPLACE)
void insertUser(User... user);
// int 影響的行數(shù)
@Update
int updateUser(User... user);
@Delete
int deleteUser(User... user);
@Query("DELETE FROM USER")
void deleteUser();
@Query("SELECT * FROM USER ORDER BY ID DESC")
List<User> getAllUser();
@Query("SELECT * FROM USER ORDER BY ID DESC")
LiveData<List<User>> getAllUserLive();
}
**添加Room數(shù)據(jù)庫(kù)**
//exportSchema = false 是不會(huì)導(dǎo)出 schemas json 結(jié)構(gòu)
@Database(entities ={User.class}, version =2, exportSchema =true)
public abstract class UserDatabase extends RoomDatabase {
public abstract UserDao getUserDao();
private static UserDatabase userDatabase;
synchronized public static UserDatabase getUserDatabase(Context context) {
if (null ==userDatabase) {
userDatabase =Room.databaseBuilder(context.getApplicationContext(),UserDatabase.class,"android_room_dev.db")
.allowMainThreadQueries()
.addMigrations(migration) //保留原有數(shù)據(jù)
.build();
}
return userDatabase;
}
static final Migration migration =new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE user ADD COLUMN type INTEGER NOT NULL DEFAULT 1");
//sqlLet沒(méi)有刪除字段語(yǔ)句钓葫,只能創(chuàng)建新的數(shù)據(jù)庫(kù)定義需要的字段,將原有數(shù)據(jù)庫(kù)數(shù)據(jù)復(fù)制過(guò)去票顾,刪除舊數(shù)據(jù)庫(kù)后再將新數(shù)據(jù)庫(kù)重命名
}
};
}
Room數(shù)據(jù)庫(kù)必須是一個(gè)繼承自RoomDatabase的抽象類(lèi)础浮。通常情況下應(yīng)用內(nèi)應(yīng)該只有一個(gè)Room數(shù)據(jù)庫(kù)實(shí)例。
**在demo中的簡(jiǎn)單使用**
public class MainActivity extends AppCompatActivity {
TextView tvAdd;
TextView tvUpdate;
TextView tvDelete;
TextView tvQuery;
TextView tvQueryAll;
TextView tvContent;
UserDatabase userDatabase;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
userDatabase =UserDatabase.getUserDatabase(this);
setContentView(R.layout.activity_main);
tvAdd = findViewById(R.id.tv_add);
tvUpdate = findViewById(R.id.tv_update);
tvDelete = findViewById(R.id.tv_delete);
tvQuery = findViewById(R.id.tv_query);
tvQueryAll = findViewById(R.id.tv_queryAll);
tvContent = findViewById(R.id.tv_content);
UserDao userDao =userDatabase.getUserDao();
LiveData<List<User>> listLiveData =userDao.getAllUserLive();
listLiveData.observe(this,new Observer<List<User>>() {
@Override
public void onChanged(List<User> users) {
String s ="";
for (int i =0; i < users.size(); i++) {
User user = users.get(i);
s +="姓名:" +user.getName() +"性別:" +user.getGender() +"年齡:" +user.getAge() +"類(lèi)型:" +user.getType() +"\n";
}
tvContent.setText(s);
}
});
tvAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
User user =new User();
user.setName("張三" +new Random().nextInt(100));
user.setAge(new Random().nextInt(100));
user.setGender(new Random().nextInt(1) +"");
user.setType(new Random().nextInt(9));
userDao.insertUser(user);
}
});
tvUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
User user =users.get(0);
user.setName("瑪麗哈利");
userDao.updateUser(user);
}
});
tvDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
if(users!=null &&users.size()>0){
User user =users.get(0);
userDao.deleteUser(user);
}
}
});
tvQuery.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
List<User> users =userDao.getAllUser();
String s ="";
for (int i =0; I
User user =users.get(i);
s +="姓名:" +user.getName() +"性別:" +user.getGender() +"年齡:" +user.getAge() +"類(lèi)型:" +user.getType() +"\n";
}
Toast.makeText(MainActivity.this,s,Toast.LENGTH_LONG).show();
}
});
tvQueryAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
}
});
}
}