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

Android 用户如何将Room根据不同账户动态分库方案

前言

开发中需要根据不同用户,创建不同名称数据库。登录用户关联自己名称命名的数据库,达到分库目的。也有基于同一个数据库进行分表的操作。
这里仅介绍使用Android Room数据库,如何分库和关联已经存在的数据库。GreenDao数据库同样可以进行动态分库,原理一样。

官方Room链接

Room 持久性库在 SQLite 上提供了一个抽象层,以便在充分利用 SQLite
的强大功能的同时,能够流畅地访问数据库。具体来说,Room 具有以下优势:

  1. 针对 SQL 查询的编译时验证。
  2. 可最大限度减少重复和容易出错的样板代码的方便注解。
  3. 简化了数据库迁移路径
  4. 支持协程挂起以及flow。可以通过观察flow来同步更新ui

MVI开发范式:采用单向数据流来串联各层次结构的一种开发范式,可以将UI界面层与业务逻辑完全隔离。区别与mvvm

假定您已经了解了room数据库如何创建。room数据库创建demo

创建Room数据库

object DbManager {
    private const val DEFAULT_DB_PREFIX = "默认数据库前缀"
    lateinit var roomDb: AppDatabase
    fun getInstance(
        context: Context, userCode: String? = "当前登录用户的code"
    ): AppDatabase {
        val userCode = userCode ?: DEFAULT_DB_PREFIX
        if (userCode != DEFAULT_DB_PREFIX && roomDb.openHelper.databaseName?.contains(userCode) == true) {
            return roomDb
        } else {
            roomDb = Room.databaseBuilder(
                context,
                AppDatabase::class.java,
                userCode + DATABASE_NAME
            ).setAutoCloseTimeout(30, TimeUnit.SECONDS).build()
        }
        return roomDb
    }
}

将如上中文替换为具体的内容就可以在新用户登录成功之后,来触发数据库的创建,一般来说数据库的操作需要滞后到用户登录成功。当然,也并不是必须将数据库操作滞后到用户登录成功。滞后的目的是避免创建一个默认的数据库,与任何用户没有绑定,仅仅在用户登录成功之前存在。因为登录之后就会关联一个以用户code为前缀的数据库,或者创建一个以用户code为前缀的数据。类似 100001_db.

Room数据库提供对表进行操作的是一个集成RoomDatabase的抽象类中的抽象方法。具体实现由Room api来实现。用户不需要关注具体如何实现数据库CRUD操作

@Database(
    entities = [LoginUser::class,], version =
    1,
    exportSchema = false
)
abstract class AppDatabase : RoomDatabase() {

    abstract fun loginUserDao(): LoginUserDao

}

如上数据库动态创建和数据表的操作都已经简单介绍。但是仅仅动态创建数据库并不能保证数据库创建之后,新的操作表会操作新创建的数据库?

why?why?why?
在这里插入图片描述

数据库创建好了。当前用户就会和新创建的数据库进行绑定,如果是已经存在的数据库就会打开数据库。为什么操作的不是新创建的数据库而是旧数据库(上一个用户创建的)

细心的话就能发现,在用户切换,或者用户被另一台设备踢掉账户之后更换账户登录,已经加载过的xxxDao并没有更新而是关联着上一个登陆用户的数据库。(如果项目中使用依赖注入框架Hilt或者其他类似的依赖注入框架,那么就需要重新设计依赖关系。对于@Singleton注释是否需要进行调整。)

解决了切换账户后更新已经加载的xxxDao文件就可以实现用户切换后自动关联以用户code为前缀创建的room数据库了。

方案一:对于xxxDao的获取,不进行缓存,每次需要操作表就重新根据数据库获取xxxDao.这样可以保证数据库对象变更后,之后获取到的xxxDao都是新数据库对象对应的Dao,不会获取到旧数据库的Dao,因为每次都是使用数据库Db对象,获取dao。

方案二: 可以在用户切换,创建数据库后。发送一个通知到所有需要操作表的已经加载到内存中的类,进行Dao更新。 可以使用flow进行更新。目的就是保证切换用户后已经加载到内存中的操作表的Dao及时更新。

如下:

@Singleton
internal class LocalDataSource @Inject constructor(
    private val appdataBase: AppDatabase
) : ILocalDataSource {

  
    override fun loginUserDao(): LoginUserDao {
        return DbManager.roomDb?.loginUserDao()!!
    }

}


interface ILocalDataSource {
    fun loginUserDao(): LoginUserDao
}

使用地方只需要依赖ILocalDataSource 接口。每次操作库表获取下对应Dao即可。

@Singleton
class UserRepository @Inject constructor(
    @ApplicationContext context: Context,
    private val localDataSource: ILocalDataSource,
  
) :  {

    fun Dao() = localDataSource.loginUserDao()
    fun getLoginUserList() = Dao().getLoginUsers()
}

总结:

将Room根据不同账户动态分库,主要分为两步,一,根据登录用户code+db,创建数据库。二,解决已经加载过的Dao,在用户切换之后自动更新。满足了就可以实现该方案。主要考虑用户切换和用户被踢场景如何更新加载过的Dao。

相关文章:

  • 539、RabbitMQ详细入门教程系列 -【100%消息投递消费(一)】 2022.08.31
  • 基于信贷业务的量化风险评估简述
  • 项目经理如何做好任务分解,制定项目计划
  • 高级JAVA面试题详解(一)——CurrentHashMap、HashMap、HashTable的区别
  • Dart 2.18 发布,Objective-C 和 Swift interop
  • learn threejs (最小化例子)
  • Flask学习(四)-------蓝图
  • 牛客多校2 - Ancestor(LCA,前后缀)
  • 【毕业设计】深度学习垃圾分类系统 - 机器视觉
  • Linux 编写shell脚本记录操作用户日志信息
  • 从零开始配置vim(19)——终端配置
  • 岑溪洁净实验室设计布局规划总结
  • 要不要做全链路压测
  • node.js云学堂微信小程序学习系统的设计与实现毕业设计源码011735
  • 前端知识3-JavaScript
  • “大数据应用场景”之隔壁老王(连载四)
  • 【Amaple教程】5. 插件
  • 230. Kth Smallest Element in a BST
  • Android优雅地处理按钮重复点击
  • - C#编程大幅提高OUTLOOK的邮件搜索能力!
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • GraphQL学习过程应该是这样的
  • Hexo+码云+git快速搭建免费的静态Blog
  • httpie使用详解
  • Iterator 和 for...of 循环
  • JavaScript 是如何工作的:WebRTC 和对等网络的机制!
  • React 快速上手 - 07 前端路由 react-router
  • SQLServer之创建显式事务
  • 初识 webpack
  • 关于 Cirru Editor 存储格式
  • 官方解决所有 npm 全局安装权限问题
  • 基于axios的vue插件,让http请求更简单
  • 前端工程化(Gulp、Webpack)-webpack
  • 少走弯路,给Java 1~5 年程序员的建议
  • 使用Envoy 作Sidecar Proxy的微服务模式-4.Prometheus的指标收集
  • 一道面试题引发的“血案”
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • ​Linux Ubuntu环境下使用docker构建spark运行环境(超级详细)
  • ​油烟净化器电源安全,保障健康餐饮生活
  • !!Dom4j 学习笔记
  • # 透过事物看本质的能力怎么培养?
  • #LLM入门|Prompt#1.7_文本拓展_Expanding
  • (13)[Xamarin.Android] 不同分辨率下的图片使用概论
  • (4.10~4.16)
  • (java)关于Thread的挂起和恢复
  • (rabbitmq的高级特性)消息可靠性
  • (阿里云万网)-域名注册购买实名流程
  • (二)c52学习之旅-简单了解单片机
  • (二)什么是Vite——Vite 和 Webpack 区别(冷启动)
  • (附源码)ssm智慧社区管理系统 毕业设计 101635
  • (三)uboot源码分析
  • (实战)静默dbca安装创建数据库 --参数说明+举例
  • (一)C语言之入门:使用Visual Studio Community 2022运行hello world
  • (转)EXC_BREAKPOINT僵尸错误
  • (转)负载均衡,回话保持,cookie