赞
踩
Room在·SQLite上提供了抽象层,以便于更加流畅的访问数据库,对数据库进行操作。主要由Database,Entity,Dao这三部分组成:
包含数据库持有者,并作为应用已保留的持久关系型数据的底层连接的主要接入点。简单来说,就是通过这个类构造的对象,调用抽象方法构造的Dao对象去对数据库中的表进行增删改查。需注意以下写法:
@Database(entities = {User.class}, version = 1)
public abstract class AppDatabase extends RoomDatabase {
public abstract UserDao userDao();
}
示例代码:
@Entity(tableName = "users")
public class User {
@PrimaryKey
public int uid;
@ColumnInfo(name = "first_name")
public String firstName;
@ColumnInfo(name = "last_name")
public String lastName;
}
-1 默认情况下,Entity类里面的字段都会生成相应的类,如果不想产生相应的类,需用@Ignore标注,
代码如下:
@Entity
public class User {
@PrimaryKey
public int id;
@Ignore
Bitmap picture;
}
@Entity(foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "user_id"))
public class Book {
@PrimaryKey public int bookId;
public String title;
@ColumnInfo(name = "user_id") public int userId;
}
其中entity = User.class表示要引用的外键的类, parentColumns = "id"表示外键在要引用的类里面的列名, childColumns = "user_id"表示在这个表中对应的列名。
示例代码:
@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); }
需注意以下:
需在app目录下的build.gradle的dependencies中添加如下代码:
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 - Kotlin Extensions and Coroutines support for Room implementation "androidx.room:room-ktx:$room_version" // optional - RxJava support for Room implementation "androidx.room:room-rxjava2:$room_version" // optional - Guava support for Room, including Optional and ListenableFuture implementation "androidx.room:room-guava:$room_version" // Test helpers testImplementation "androidx.room:room-testing:$room_version"
这样做完常会出现一个Kotlin的jar包不能够安装的问题,会导致build时会超时,完成不了,导致Room不能够使用,解决办法:在于app同级的build.gradle中的allprojects里的repositories里如下写法:
allprojects {
repositories {
maven{url "https://kotlin.bintray.com/kotlinx/"}
google()
jcenter()
}
}
采用单例模式反回数据库对象。相关代码:
@Database(entities = {User.class},version = 1) public abstract class AppDatabase extends RoomDatabase { private static final String DB_NAME ="uers.db"; private static volatile AppDatabase instance; static synchronized AppDatabase getInstance(Context context){ if(instance==null){ instance=create(context); } return instance; } private static AppDatabase create(final Context context){ return Room.databaseBuilder(context, AppDatabase.class, DB_NAME) //.addMigrations(MIGRATION_1_2) //数据库升级,可以对数据库进行更改 .build(); } public abstract UserDao userDao(); }
这样反回一个数据库对象,生成了一个指定名字的数据库。
在上述代码中加入以下代码:
static final Migration MIGRATION_1_2=new Migration(1,2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
//对数据库结构进行修改的操作
}
};
MIGRATION_1_2表示从第一个版本到第二个版本,对应的Migration(1,2)。
可以在文件中查看数据库的变化情况:
在app目录下的app目录下的build.gradle中加入如下代码:
android {
defaultConfig {
javaCompileOptions {
annotationProcessorOptions {
arguments = ["room.schemaLocation": "$projectDir/schemas".toString()]
//指定数据库schema导出的位置
}
}
}
}
可以在schemas目录中看到一个json文件,里面就有相关记录。
表结构的修改是写在数据库升级里面的。
示例一个对数据库中表的结构修改且不丢失数据的操作。
//对数据库的表结构进行修改,而不丢失数据
database.execSQL("create table temp_user("+
"id integer primary key not null,"+
"first_name TEXT,"+"last_name text)"); //创建表
database.execSQL("insert into temp_user(id,first_name,last_name)"+
"select id,first_name,last_name from user"); //从原先表中导入数据
database.execSQL("drop table user"); //删除表
database.execSQL("alter table temp_user rename to user");//重命名
@Entity public class User { @PrimaryKey public int uid; @ColumnInfo(name="first_name") public String firstName; @ColumnInfo(name="last_name") public String lastName; public User() {} @Ignore public User(int uid, String firstName, String lastName) { this.uid = uid; this.firstName = firstName; this.lastName = 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; } }
这个类的写法须遵循javabeans的写法,值得注意的就是要有一个空的构造方法,如果有其他的构造方法
需要用 @Ignore来标识。
@Dao public interface UserDao { @Query("select * from user") List<User> getAll(); @Query("select * from user where first_name like :first and " + "last_name like :last limit 1") User findByName(String first,String last); @Query("select * from user where uid= :id") User findById(int id); @Update void update(User user); @Insert void insert(User user); @Delete void delete(User user); }
用了recycleView来显示数据库中的内容。注意几点:
package com.app.roomdemo; import androidx.appcompat.app.AppCompatActivity; import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; import androidx.room.Room; import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.TextView; import android.widget.Toast; import java.security.PrivateKey; import java.util.ArrayList; import java.util.List; public class MainActivity extends AppCompatActivity { private RecyclerView recyclerView_show; EditText editText_id; EditText editText_first; EditText editText_last; private Button button_put; private Button button_insert; private Button button_delete; private Button button_change; private Button button_search; private UserDao userDao; ArrayList<User> userList =new ArrayList<>(); private int id; private String first; private String last; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); AppDatabase db =AppDatabase.getInstance(getApplicationContext()); userDao = db.userDao(); initView(); initrecycleView(true); Log.e("MainActivity","setAdapter"); View.OnClickListener mylistener = new View.OnClickListener() { @Override public void onClick(View v) { switch (v.getId()) { case R.id.put: put(); break; case R.id.change: change(MainActivity.this); break; case R.id.search: search(MainActivity.this); break; case R.id.delete: delete(MainActivity.this); break; case R.id.insert: insert( MainActivity.this); break; default: break; } } }; button_put.setOnClickListener(mylistener); button_search.setOnClickListener(mylistener); button_insert.setOnClickListener(mylistener); button_delete.setOnClickListener(mylistener); button_change.setOnClickListener(mylistener); } //删除操作 private void delete(final Context context) { new Thread(new Runnable() { @Override public void run() { User user=new User(id,first,last); userDao.delete(user); initrecycleView(true); } }).start(); } //插入操作 private void insert(final Context context) { new Thread(new Runnable() { @Override public void run() { User user=new User(id,first,last); userDao.insert(user); initrecycleView(true); } }).start(); } //按Id搜索操作 private void search(final Context context) { initrecycleView(false); } //更新操作 private void change(final Context context) { new Thread(new Runnable() { @Override public void run() { User user= new User(id,first,last); userDao.update(user); initrecycleView(true); } }).start(); } //数据提交 private void put(){ if(!editText_id.getText().toString().isEmpty()){ id=Integer.parseInt(editText_id.getText().toString()); first=editText_first.getText().toString(); last=editText_last.getText().toString(); } } //显示所有的内容 private ArrayList<User> show(final Boolean is_show_all){ new Thread(new Runnable() { @Override public void run() { if(is_show_all){ userList=new ArrayList<User>(); userList=(ArrayList<User>) userDao.getAll(); } else{ userList=new ArrayList<User>(); User user=new User(); user=userDao.findById(id); if(user!=null) userList.add(user); } } }).start(); return userList; } //初始化各组件对象 private void initView() { recyclerView_show=(RecyclerView)findViewById(R.id.recyclerView_show); button_put=(Button)findViewById(R.id.put); button_search=(Button)findViewById(R.id.search); button_change=(Button)findViewById(R.id.change); button_insert=(Button)findViewById(R.id.insert); button_delete=(Button)findViewById(R.id.delete); editText_id=(EditText)findViewById(R.id.id); editText_first=(EditText)findViewById(R.id.first); editText_last=(EditText)findViewById(R.id.last); } //执行更新UI操作 private void initrecycleView(Boolean is_show_all){ userList=show(is_show_all); new Handler(this.getMainLooper()).post(new Runnable() { @Override public void run() { LinearLayoutManager layoutManager=new LinearLayoutManager(MainActivity.this); recyclerView_show.setLayoutManager(layoutManager); UserAdapter adapter=new UserAdapter(MainActivity.this,userList); recyclerView_show.setAdapter(adapter); } }); } }
由于使用了延迟更新UI,则执行操作可能不会马上见效。
Adapter及相关布局文件就不提供了,提供在educoder上。
操作前:
插入操作:
更改操作:
删除操作:
Room框架比较直接,且功能分配明确,十分简洁
再者,一定记住数据库操作要在子线程中完成,还有插入操作时,如果没有指定冲突的方法时,如果插入的数据主键已经存在数据库里面的某个项,那么会直接闪退。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。