Room介绍
room是Google官方推荐的ORM数据库框架,抽象出sqlite访问的数据库。
包含三大组件:
- Entity 定义 表结构,每个entity类对一个表,默认会把entity类所有字段都创建为表字段
- Dao 定义entity类的CRUD(增删查改)功能
- Database 数据库的访问入口,注解定义数据库的实体表,数据库版本控制,表结构导出、表结构修改等都在这里处理
步骤
1.添加依赖
def room_version = '2.3.0-alpha04'
implementation rootProject.ext.dependencies.room_runtime
annotationProcessor rootProject.ext.dependencies.room_compiler
androidTestImplementation rootProject.ext.dependencies.room_testing
2.定义Entity实体表
@Entity 注解并在@Database 注解中的 entities 属性所引用,Room就会在数据库中为这个被 @Entity 注解的类创建一张表
@PrimaryKey 每个entity至少要有一个主键(PrimaryKey),autoGenerate表示这个值自动生成
@Entity(primaryKeys = {"xxx", "xxx"}) 如果是复合主键的话, 你需要使用注解@Entity的primaryKeys属性
@Entity(primaryKeys = {"firstName", "lastName"})
public class User {
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
@ColumnInfo(name = "xxx") 定义表字段,也可以不使用此注解,默认为所有属性生成表字段
@Ignore 如果Engity类中某个属性不想保存到数据库,可以使用@Ignore注解忽略
@Entity
public class User {
@PrimaryKey
public int id;
public String firstName;
public String lastName;
@Ignore
Bitmap picture;
}
@Entity(indices = {@Index("name"), @Index(value = {"last_name", "address"})}) 为了加速查询速度. 要给实体添加索引
@Entity(indices = {@Index("name"),
@Index(value = {"last_name", "address"})})
public class User {
@PrimaryKey
public int id;
public String firstName;
public String address;
@ColumnInfo(name = "last_name")
public String lastName;
@Ignore
Bitmap picture;
}
@Entity(foreignKeys = @ForeignKey(entity = User.class,
parentColumns = "id",
childColumns = "user_id")) 设置外键
@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;
}
@Embedded注解来表示一个对象
public class Address {
public String street;
public String state;
public String city;
@ColumnInfo(name = "post_code")
public int postCode;
}
@Entity
public class User {
@PrimaryKey
public int id;
public String firstName;
@Embedded
public Address address;
}
demo:
package com.wrs.project.module.app.common.database.entity;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import androidx.annotation.NonNull;
@Entity(tableName = "Article")
public class Article {
@PrimaryKey(autoGenerate = true)
private int id;
private String author;
private String title;
private String content;
private String token;
private int comments;
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getToken() {
return token;
}
public void setToken(String token) {
this.token = token;
}
public int getComments() {
return comments;
}
public void setComments(int comments) {
this.comments = comments;
}
}
3. 定义DAO
简单查询
@Dao
public interface MyDao {
@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);
}
嵌套查询
@Dao
public interface MyDao {
@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);
}
@Dao
public interface MyDao {
@Query("SELECT user.name AS userName, pet.name AS petName "
+ "FROM user, pet "
+ "WHERE user.id = pet.user_id")
public LiveData<List<UserPet>> loadUserAndPetNames();
// You can also define this class in a separate file, as long as you add the
// "public" access modifier.
static class UserPet {
public String userName;
public String petName;
}
}
demo
package com.wrs.project.module.app.common.database.dao;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Delete;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
import com.wrs.project.module.app.common.database.entity.Article;
import java.util.List;
@Dao
public interface ArticleDao {
/**
* 增
* @param entities
*/
@Insert
void insert(Article... entities);
/**
* 删
* @param entities
*/
@Delete
void delete(Article... entities);
/**
* 查
* @param title
*/
@Query("SELECT * FROM Article WHERE title = :title")
List<Article> findByTitle(String title);
/**
* 查
* @param titles
*/
@Query("SELECT * FROM Article WHERE title IN (:titles)")
List<Article> findInTitles(List<String> titles);
/**
* 改
* @param entities
*/
@Update
void update(Article... entities);
@Insert(onConflict = OnConflictStrategy.REPLACE)
List<Long> insertAll(List<Article> entities);
@Delete
void delete(Article entity);
@Query("DELETE FROM Article")
void deleteAll();
@Delete
void deleteArticle(Article entity);
@Query("SELECT * FROM Article")
List<Article> findAll();
@Query("SELECT * FROM Article")
LiveData<List<Article>> loadSignList();
}
4. 定义Database
package com.wrs.project.module.app.common.database;
import android.content.Context;
import androidx.room.Room;
import androidx.room.RoomDatabase;
import androidx.room.TypeConverters;
import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import com.wrs.project.module.app.common.database.conversion.ConversionFactory;
import com.wrs.project.module.app.common.database.dao.ArticleDao;
import com.wrs.project.module.app.common.database.entity.Article;
@androidx.room.Database(
entities = { Article.class}, // 声明需要创建表的实体
version = 2, // 数据库版本号
exportSchema = true // 表结构是否需要导出
)
@TypeConverters({ConversionFactory.class}) // 属性类型转换,这里值转换了Date类
public abstract class Database extends RoomDatabase {
public abstract ArticleDao articleDao(); // 声明每个entity的dao类
private static Database sInstance; // 创建访问数据库比较耗资源,生成单例方便访问
public static Database getInstance(final Context context) {
if (sInstance == null) {
synchronized (Database.class) {
if (sInstance == null) {
sInstance = create(context.getApplicationContext());
}
}
}
return sInstance;
}
private static Database create(final Context context) {
return Room.databaseBuilder(
context,
Database.class,
"phonesign_db")
.addMigrations(MIGRATION_1_2) // 构建版本升级时表结构的变化
.allowMainThreadQueries()
.build();
}
private static Migration MIGRATION_1_2 = new Migration(1,2) {
@Override
public void migrate(SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE Article "
+ " ADD COLUMN token TEXT");
database.execSQL("ALTER TABLE Article "
+ " ADD COLUMN comments INTEGER NOT NULL DEFAULT 0");
}
};
}
5. 测试
package com.wrs.project.module.app.common;
import android.content.Context;
import android.util.Log;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.platform.app.InstrumentationRegistry;
import com.wrs.project.module.app.common.database.DBService;
import com.wrs.project.module.app.common.database.entity.Article;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import static org.junit.Assert.assertEquals;
@RunWith(AndroidJUnit4.class)
public class DatabaseInstrumentedTest {
@Test
public void useAppContext() {
// Context of the app under test.
Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
AppMgr.context = appContext;
AppMgr.debug = true;
List<Article> list = new ArrayList<>();
for (int i = 0; i < 6; i++) {
Article entity = new Article();
entity.setTitle("title" + i);
entity.setDate(new Date());
list.add(entity);
}
DBService.insertAll(list);
List<Article> resultList = DBService.findAll();
if (null != resultList && resultList.size() > 0) {
for (int i = 0; i < resultList.size(); i++) {
Article entity = resultList.get(i);
Log.e("article", entity.getTitle());
}
}
List<Article> entityList = DBService.findByTitle("title5");
Log.e("article", entityList.toString());
}
}
如果觉得可以就点个👍吧,欢迎粉丝收藏,土豪打赏,您的关注就是我们创作的动力!
读者有什么想看的相关技术篇章,欢迎评论留言!
QQ交流群:908058499
项目源码:https://codechina.csdn.net/android1/projectbasic
上篇:无 目录 下篇:android专题-蓝牙扫描、连接、读写
网友评论