当前位置: 首页 > news >正文

Android Room DataBase

Room数据库是在Sqlite的基础上,进行了封装和优化。这让我们可以摆脱,繁琐的数据库操作

在module的gradle里面,加入:

dependencies {annotationProcessor "androidx.room:room-compiler:2.3.0"implementation 'androidx.room:room-common:2.3.0'implementation 'androidx.room:room-runtime:2.3.0'implementation 'androidx.room:room-runtime:2.3.0'}

一、Room的三大组件

Room的三大组件,换言之,即是Room由哪三个东西组成。

    Entity:每一个Entity是一个类,同时也是一张表。默认情况下,类名即是表名,字段名,即是字段名。可以通过注解的形式,进行自定义表名和字段名,这个在下一篇会详细讲解。
    Dao:每一个Dao,定义了一组对Entity的操作(Method, 即方法)。比如,增删查改。

    DataBase:DataBase类似于Manager,通过DataBase,可以获取到任意有绑定到DataBase的Dao对象,再通过Dao对象,就可以对每一个Entity进行操作。作为一个DataBase类,必须满足以下三个条件:

    1、DataBase类必须是继承自RoomDataBase,并且其本身,必须是抽象类。
    2、通过在头部以注解的方式(后面会讨论如何做),添加一组Entity。这句话的意思是,只要Entity添加在DataBase类的头部,那该DataBase就可以,对已添加的Entity进行操作。
    3、至少包含一个不带参数的抽象方法,该方法返回一个已绑定的Entity所对应的Dao类型。

二、如何定义Entity

每一个Entity类,都会在其类名定义的前一行,增加一个注解@Entity,来标识该类是Room的一个Entity。每一个字段都有一个注解,这里就列举几个比较简单常见的:

1、@PrimaryKey,表示该字段是主键、@NonNull 表示该字段不允许为空。
2、@ColumnInfo(name = “last_name”),表示该字段是表中的一个字段,字段名为自定义的last_name。
3、@Ignore,表示不对字段进行存储。
4、@Entity(tableName ="meals"),实际数据库表名为meals
其他:

5、主键ID的自增(autoGenerate)。只要设置PrimaryKey的autoGenerate属性为true即可

@PrimaryKey(autoGenerate = true)
 private int id;

6、联合主键(primaryKeys)。与单主键不同的是,联合主键的定义,是作为@Entity的属性的形式,被定义的。并且,关键字是primaryKeys,不是primaryKey,多了一个s。代码如下:

@Entity(primaryKeys = {"firstName", "lastName"})
class User {

    public String firstName;
    public String lastName;

    @Ignore
    Bitmap picture;
}

7、创建索引与唯一性约束。

我们可以通过创建索引,来提高查询的效率,其原理是索引原理。同时,可以创建字段的唯一性约束,来避免创建相同的数据。因为在一张表中,除了主键(id)字段的每条数据都是不同之外,有可能还存在其它字段的数据也不允许重复,比如身份证号码,这时就需要添加唯一性约束。

a)、索引(indices)

创建索引的根本目的,是提高查询的效率。那么,如何在Entity中,创建索引呢?

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

    public String firstName;
    public String address;

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

    @Ignore
    Bitmap picture;
}

b)、唯一性约束(unique)

有时候,我们可能想要某一字段,或多个字段的组合的数据,在表中是唯一的,不重复的。那么,我们可以使用唯一性约束。代码如下:

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

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

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

    @Ignore
    Bitmap picture;
}

三、如何定义Dao

@Dao
public interface dishmealDao {@Query("SELECT * FROM meals")List<dishmeal> getAllMeals();// 获取表中记录的数量@Query("SELECT COUNT(*) FROM meals")int getMealsCount();@Query("SELECT * FROM meals")Cursor getMealCursor();@Query("SELECT * FROM meals WHERE MealID=:MealID")dishmeal getMeal(String MealID);@Query("select * from meals where MealID in (:mealids)")List<dishmeal> loadMealsByIds(String[] mealids);@Query("select * from meals where MealName like :first or MealSpell like :last ")//limit 1List<dishmeal> findMealsByName(String first, String last);@Query("SELECT * FROM meals WHERE MealName=:MealName")List<dishmeal> getMealsByName(String MealName);@Query("DELETE FROM meals")int deleteAllMeals();@Query("DELETE FROM meals WHERE MealID=:MealID")int delete(String MealID);@Insertlong insert(dishmeal meal);@Updateint update(dishmeal... meals); //动态根据查询条件,查询@RawQueryList<dishmeal> getMyEntities(SupportSQLiteQuery query);}

每一个Dao类,都会在其类名定义的前一行,增加一个注解@Dao,来标识该类是Room的一个Dao。每一个方法,都有一个注解,用来表示,这个方法能对表进行的操作。这里,同样例举几个常见的注解:

1、@Query,表示查询数据。具体的sql语句写在其后的大括号里面,记得要加上” “双引号。
2、@Insert,表示插入数据。(onConflict = OnConflictStrategy.REPLACE),这段表示,如果插入有冲突,就直接替换掉旧的数据。
3、@Update,表示更新数据。
4、@Delete,表示删除数据


四、如何定义一个DataBase?

@Database(entities = { User.class,dishmeal.class }, version = 2, exportSchema = false)
public abstract class AppDatabase extends RoomDatabase {private static final String DB_NAME = "AppDatabase.db";private static volatile AppDatabase instance;private static Context mContex = null;public static synchronized AppDatabase getInstance(Context context) {mContex = context;if (instance == null) {instance = create(context);}return instance;}private static AppDatabase create(final Context context) {AppDatabase database = Room.databaseBuilder(context,AppDatabase.class,DB_NAME)
//                .addMigrations(MIGRATION_1_2) // , MIGRATION_2_3, MIGRATION_3_4, MIGRATION_1_4).fallbackToDestructiveMigration().build();// 获取数据库文件路径并打印String dbPath = context.getDatabasePath(DB_NAME).getAbsolutePath();Logger.d("Database path: " + dbPath);return database;}public static void Refdatabase(){if (instance!=null) {instance.close();instance = create(mContex);}}//动态设置查询条件public static List<dishmeal> getMealsEntities(QueryFactory queryFactory) {return instance.getmealDao().getMyEntities(queryFactory.createQuery());}public abstract UserDao getUserDao();public abstract dishmealDao getmealDao();}

每一个DataBase类,都会在其类名定义的前一行,增加一个注解@Database,来标识该类是Room的一个Database。其中,entities字段,表示该DataBase,绑定的表。多个表以逗号分开。version字段,表示该DataBase的版本。

五、如何使用他们

先定义 dishmealDao对象dtMeals,再在新线程中调用dishmealDao下的方法

附件:设置动态查询条件

1)、创建接口QueryFactory,
SupportSQLiteQuery是Room数据库库在 SQLite上的抽象,它允许你构建查询并以标准的方式执行它们

public interface QueryFactory {
    SupportSQLiteQuery createQuery();
}

2)、定义MyQueryFactory 重新SupportSQLiteQuery 方法

public class MyQueryFactory implements QueryFactory {private String whereClause;private String[] whereArgs;private String tablename;public MyQueryFactory(String tablename,String whereClause, String[] whereArgs) {this.whereClause = whereClause;this.whereArgs = whereArgs;this.tablename=tablename;}@Overridepublic SupportSQLiteQuery createQuery() {return new SimpleSQLiteQuery("SELECT * FROM   " + tablename + " " + whereClause, whereArgs);}
}

3)、在@Dao里设置动态根据查询条件,查询

@RawQuery List<dishmeal> getMyEntities(SupportSQLiteQuery query);

4)、在class AppDatabase extends RoomDatabase定义:

//动态设置查询条件

public static List<dishmeal> getMealsEntities(QueryFactory queryFactory)
{ return instance.getmealDao().getMyEntities(queryFactory.createQuery()); }

5)、应用例子:

String whereClause =" WHERE MealName like ? or MealID LIKE ? ";
String[] whereArgs = new String[]{"%水%","%2%"};//
QueryFactory queryFactory = new MyQueryFactory("meals",whereClause, whereArgs);
List<dishmeal> mlst= AppDatabase.getInstance(ShowTable.this).getMealsEntities(queryFactory);


http://www.mrgr.cn/news/6484.html

相关文章:

  • LP2801A/B/C/D/E 输出电压可调3.3V~24V,输出电流100mA~400mA
  • 一款好看的WordPress REST API 主题
  • 微知-PCIe配置空间中哪个字段表示设备类型?有哪三种类型?哪个字段表示厂商ID
  • oracle 事务回滚
  • 在Flux和Ideogram 2.0的竞争压力下,Midjourney每日开放25张免费额度
  • function call使用基础
  • 汇编语言:adc指令 和 sbb指令
  • 【前端基础篇】JavaScript基础介绍
  • 【知识图谱】2.知识抽取与知识存储
  • Java设计模式之策略模式详细讲解和案例示范
  • Objective-C中的查询大师:深入探索NSPredicate与NSExpression
  • EPCE-HDR
  • 基于单片机的仿生水母水下机器人设计
  • 电机学习记录
  • java整合Redis
  • 大话设计模式解读06-原型模式
  • Nginx服务器申请及配置免费SSL证书
  • 8.22-docker的部署及其使用
  • 使用uart串口配置TMC2209模块
  • Spring系列之Spring Cache缓存注解的使用